GIT 43c5bc228b7710473d4d4b7718fa91ac3e6b66f6 git+ssh://master.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6.git commit 43c5bc228b7710473d4d4b7718fa91ac3e6b66f6 Author: Paul Mundt Date: Tue Dec 18 09:43:35 2007 +0900 sh: Provide a stubbed __set_fixmap() for nommu. Signed-off-by: Paul Mundt commit e2117548870194742add3695cb96b7659316f416 Author: Paul Mundt Date: Tue Dec 18 09:43:15 2007 +0900 sh: Always use CONFIG_HZ for HZ. Currently the wdt forces HZ=1000 and sidesteps CONFIG_HZ completely. This is a remnant from when HZ was hardcoded and before CONFIG_HZ was introduced. Additionally, not all of the timers have this requirement these days, so it's also an artificial limitation. Just kill it off and use CONFIG_HZ directly. Reported-by: H. Peter Anvin Signed-off-by: Paul Mundt commit 7d1adc99132ce35440997605ccf8672590ec9433 Author: Joe Perches Date: Tue Dec 18 09:40:33 2007 +0900 sh: include/asm-sh/: Spelling fixes. Signed-off-by: Joe Perches Signed-off-by: Paul Mundt commit 9e62617c29645821a8fdcbfd73c560a60e3cacad Author: Joe Perches Date: Tue Dec 18 09:40:03 2007 +0900 sh: arch/sh/: Spelling fixes. Signed-off-by: Joe Perches Signed-off-by: Paul Mundt commit 2418cbd886397f9cf673ed383d57df32b3048586 Author: Paul Mundt Date: Mon Dec 17 16:08:49 2007 +0900 sh: Fix up KERNEL_ENTRY calculation for uImage. Signed-off-by: Paul Mundt commit 37670d7486f947b71db1f61215bcf50a5e79384b Author: Paul Mundt Date: Mon Dec 17 16:00:25 2007 +0900 sh: Fix up binfmt_flat compile warnings. Signed-off-by: Paul Mundt commit db32f715988dba044639e4e85f49c0dc812036d9 Author: Paul Mundt Date: Mon Dec 17 15:59:38 2007 +0900 sh: Kill off pgtable.h from scatterlist.h. Fixes up the mmc build. Signed-off-by: Paul Mundt commit b6aef5d890e7d13e6e2a1de5635ea28da0f2007d Author: Paul Mundt Date: Mon Dec 17 10:52:37 2007 +0900 sh: Fix up switch_to() type casts. Signed-off-by: Paul Mundt commit b6be0e5135076db0b643ad244b412d64958de31d Author: Paul Mundt Date: Mon Dec 17 10:52:11 2007 +0900 sh: Stub in page_table_range_init() on nommu. Signed-off-by: Paul Mundt commit 3c2f35469b371cf4209dd46d3f7807d6d67bdcf8 Author: Harvey Harrison Date: Tue Dec 11 13:49:35 2007 +0900 sh: Use def_bool where possible. Change occurances of: bool default X to: def_bool X Change ocurances of: bool "Foo" default X to: def_bool X prompt "Foo" Signed-off-by: Harvey Harrison Signed-off-by: Paul Mundt commit a1719e345619c4935ed49a4272c2f483e340d9f5 Author: Paul Mundt Date: Mon Dec 10 16:33:32 2007 +0900 sh: Kill off superfluous __KERNEL__ check in asm/elf.h. Signed-off-by: Paul Mundt commit b961728ada00115fd48b2a720403cba81487f01d Author: Paul Mundt Date: Mon Dec 10 16:21:57 2007 +0900 sh: Provide the FPSCR init through AT_FPUCW. Signed-off-by: Paul Mundt commit caaa6afcc7665741fa7426c99f0589ebd0ceab57 Author: Paul Mundt Date: Mon Dec 10 16:06:32 2007 +0900 sh: Use utsname()->machine for ELF_PLATFORM. Signed-off-by: Paul Mundt commit 74111bda3b4b6afc0e249f366e3bd69f9145ad38 Author: Paul Mundt Date: Mon Dec 10 15:50:28 2007 +0900 sh: Encode L1/L2 cache shape in auxvt. This adds in the L1I/L1D/L2 cache shape support to their respective entries in the ELF auxvt, based on the Alpha implementation. We use this on the userspace libc side for calculating a tightly packed SHMLBA amongst other things. Signed-off-by: Paul Mundt commit 7846d641a291806e22a4673867563425f27e9c46 Author: Stuart Menefy Date: Fri Nov 30 18:42:27 2007 +0900 sh: Support denormalization on SH-4 FPU. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 3815228c7b2dd6042cb3facf07f3abf77204d640 Author: Thomas Betker Date: Fri Nov 30 18:22:10 2007 +0900 sh: Fix up uImage target entry point. This patch changes the uImage target so that it generates a wrapped compressed vmlinux, rather than a wrapped zImage. The previous version matched the ARM, this version matches the PPC. However I would question how useful a self decompressing image is with a boot loader which does decompression, so I think this is more useful. I also feel it matches the descrition in the help text ("Compressed kernel image") better. Signed-off-by: Thomas Betker Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 9c5a4eec79b3eb8876d2e7fddfa1e040a7650e55 Author: Stuart Menefy Date: Fri Nov 30 18:16:23 2007 +0900 sh: get_user fixes and nommu consolidation. When a get_user(to, from++) is called the pointer increment is performed after its first usage, in the specific after the __add_ok invokation. This causes a wrong get_user return value, putting a wrong character in the destination variable. This patch solves the problem using a new temporary pointer. Additionally this reworks the use of the register banks, allowing for consolidation between the MMU and nommu implementations. Signed-off-by: Carmelo Amoroso Signed-off-by: Giuseppe Condorelli Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 2152a7cf3de31a1adf4890a446311a4321433127 Author: Stuart Menefy Date: Fri Nov 30 18:05:18 2007 +0900 sh: Document PTEL 31:29 use on PTEA-wielding parts. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 1092d6b8519bb66f98a7b292032bb3f522af6842 Author: Stuart Menefy Date: Fri Nov 30 17:59:55 2007 +0900 sh: Populate swapper_pg_dir with fixmap range. This saves us from having to use kmalloc() for the fixmap entries, which is needed early for the uncached fixmap. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 159cbe7946e7c162d0789a2db70984794e5e8a37 Author: Stuart Menefy Date: Fri Nov 30 17:52:53 2007 +0900 sh: Clean up places that make 29-bit physical assumptions. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 4cce4ee508df8244a97d254fa5593e8e3d36e658 Author: Stuart Menefy Date: Fri Nov 30 17:06:36 2007 +0900 sh: Preparation for uncached jumps through PMB. Presently most of the 29-bit physical parts do P1/P2 segmentation with a 1:1 cached/uncached mapping, jumping between the two to control the caching behaviour. This provides the basic infrastructure to maintain this behaviour on 32-bit physical parts that don't map P1/P2 at all, using a shiny new linker section and corresponding fixmap entry. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 515d6f67edc4fd00f42eb172c7e2be0433e64fa1 Author: Paul Mundt Date: Fri Nov 30 16:34:26 2007 +0900 sh: Explicit alignment for PAGE_SIZE in copy/clear_page(). Signed-off-by: Paul Mundt commit 9d381651834fccc2df9e47e36548be0604be8448 Author: Stuart Menefy Date: Fri Nov 30 16:12:36 2007 +0900 sh: GUSA atomic rollback support. This implements kernel-level atomic rollback built on top of gUSA, as an alternative non-IRQ based atomicity method. This is generally a faster method for platforms that are lacking the LL/SC pairs that SH-4A and later use, and is only supportable on legacy cores. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 690327e4038cd9bfed287830755ea07802ae1322 Author: Nobuhiro Iwamatsu Date: Fri Nov 30 12:33:17 2007 +0900 sh: Fix compile error of arch/sh/mm/pmb.c Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: Paul Mundt commit 1c661feb6f9c08e7d1634777d99ff4da558aae75 Author: Paul Mundt Date: Wed Nov 28 20:19:38 2007 +0900 sh: comment tidying for sh64->sh migration. Signed-off-by: Paul Mundt commit c36723ea7cbf2e2fa3a5799ca7d14df35bc73477 Author: Paul Mundt Date: Wed Nov 28 19:58:11 2007 +0900 sh: syscall auditing for sh5, too. Signed-off-by: Paul Mundt commit 93389b1ecbf41c0a4d5a4a1c45b2076b6987e573 Author: Paul Mundt Date: Wed Nov 28 19:14:23 2007 +0900 rtc: rtc-sh: Split out the CPU defs to asm/cpu/. With all of the different CPU types this was getting a but unwieldly. Since sh64 is now integrated, we don't have to worry about multiple architectures caring about the header definitions. Split out the defs for each asm/cpu/ to make rtc-sh slightly less visually offensive. Signed-off-by: Paul Mundt commit 19591f4392a326bc2fcf338a73587b5c92ed86d6 Author: Paul Mundt Date: Wed Nov 28 15:56:27 2007 +0900 sh: CCR1->CCR renaming for SH-2 parts. Avoid namespace collision with a CCR1 definition. The general SH code always expects CCR anyways, so there's no point in keeping the CCR1 naming around. Fixes up synclink collisions: drivers/char/pcmcia/synclink_cs.c:283:1: warning: "CCR1" redefined In file included from include/asm/cache.h:13, from include/asm/processor_32.h:15, from include/asm/processor.h:60, from include/linux/prefetch.h:14, from include/linux/list.h:8, from include/linux/module.h:9, from drivers/char/pcmcia/synclink_cs.c:38: include/asm/cpu/cache.h:21:1: warning: this is the location of the previous definition Reported-by: Andrew Morton Signed-off-by: Paul Mundt commit ffd1ff095cf2e41eb0d056b3f0d0e44159f340bf Author: Paul Mundt Date: Tue Nov 27 15:57:30 2007 +0900 sh: Bump up ARCH_KMALLOC_MINALIGN for DMA cases. Signed-off-by: Paul Mundt commit 5b6c0336683b2c207dfdce4a9ef829bcfc638671 Author: Stuart Menefy Date: Mon Nov 26 21:32:40 2007 +0900 sh: Invalidate the TLB after applying PMB mappings. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit 0190db57104c49914578c39ae74238336586209a Author: Stuart Menefy Date: Mon Nov 26 21:29:09 2007 +0900 sh: Provide a 29/32-bit physical hint for bootloaders. Shoves a magic word in to the empty_zero_page section for the bootloader to work out whether to start the kernel in 29-bit or 32-bit mode. [ Renesas CPUs already take care of the initial PMB mappings entirely in hardware and decide on 29-bit/32-bit physical depending on which pin powered up the CPU, so this is mostly for ST parts. -- PFM ]. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit dfb29bb6287ac44fe2a679a7438ccfcaa3af5160 Author: Stuart Menefy Date: Mon Nov 26 21:16:09 2007 +0900 sh: Add a printk() to warn legacy mem= growers. mem= can't be used to grow the size of kernel memory, so provide a warning to that effect. Signed-off-by: Stuart Menefy Signed-off-by: Paul Mundt commit c877de9f52585fe455967d53bafce27f4cb794e8 Author: Paul Mundt Date: Mon Nov 26 20:38:36 2007 +0900 sh: SH-2A FPU support. Signed-off-by: Kieran Bingham Signed-off-by: Paul Mundt commit 1f5dd0f62642b8fe1553b07522d620f5c7009e70 Author: Paul Mundt Date: Mon Nov 26 19:54:02 2007 +0900 sh: Add SH7263 CPU support. This adds support for the SH7263 (SH-2A) CPU. This particular CPU is a superset of SH7203, adding some additional peripheral blocks and hooking up additional (reserved on SH7203) vectors in the INTC block. No visibly nasty surprises, yet.. Signed-off-by: Paul Mundt commit 35d1d10f57c7afad97ceb8fb7a23583af098d28a Author: Paul Mundt Date: Mon Nov 26 18:17:51 2007 +0900 sh: Fix the arch/sh/kernel/traps.c build for sh32. Signed-off-by: Paul Mundt commit 4a8e02d81ea3f0c6f221c44b64fd5d77aac5ca3a Author: Paul Mundt Date: Mon Nov 26 18:17:21 2007 +0900 sh: Add SH7203 CPU support. This adds support for the SH7203 (SH-2A) CPU. Signed-off-by: Kieran Bingham Signed-off-by: Paul Mundt commit b4b36f48253a6023dfdbd02ff8be5f90fdee8695 Author: Paul Mundt Date: Mon Nov 26 17:56:31 2007 +0900 rtc: rtc-sh: SH-2A support. Trivial support for the SH-2A on-chip RTC. Signed-off-by: Paul Mundt commit d35db43bff8cc462e80c39f2c9331423c3bf9c7d Author: Yuichi Nakamura Date: Sat Nov 10 19:21:34 2007 +0900 sh: syscall audit support. Support syscall auditing.. Signed-off-by: Yuichi Nakamura Signed-off-by: Paul Mundt commit f849bbe4d2099c1c1280138940764690cf7b7b0b Author: Paul Mundt Date: Fri Nov 23 14:24:25 2007 +0900 sh: Fix up uname -m matching for native sh64. Signed-off-by: Paul Mundt commit c769274748b91b9484dd5876b4d3d64820825247 Author: Paul Mundt Date: Fri Nov 23 14:23:50 2007 +0900 sh: Move mach-cayman in with the rest of the boards. Signed-off-by: Paul Mundt commit 235d1c4cf978aa33b09676658b3cece96b8f118c Author: Paul Mundt Date: Fri Nov 23 14:17:42 2007 +0900 sh: Kill off the mach-harp and mach-sim machtypes. Signed-off-by: Paul Mundt commit b010a9b15a4ba7b925ab4b93e2d0bf536aab2ee4 Author: Paul Mundt Date: Fri Nov 23 14:02:20 2007 +0900 sh: Fix up bug trap handler build for sh32. Signed-off-by: Paul Mundt commit a127551ccdcf9348f463ec97b4747f78ae8e48b9 Author: Paul Mundt Date: Fri Nov 23 13:55:02 2007 +0900 sh: Build fixes for lib32 clear_page. Signed-off-by: Paul Mundt commit cccd6a402a4c51d612f717a47dee9edb9f003ef4 Author: Paul Mundt Date: Fri Nov 23 13:54:34 2007 +0900 sh: Fix up default zImage target for sh32. This was using the absolute path, which was confusing the make target. Switch it to just 'zImage', as per powerpc. Signed-off-by: Paul Mundt commit 7070da1cbe01d2534607a3bf7945e88d0775527e Author: Paul Mundt Date: Thu Nov 22 17:30:50 2007 +0900 sh: Bring the SH-5 FPU in line with the SH-4 FPU API. Signed-off-by: Paul Mundt commit 8c9b625a1e0931f092290b7c7206df497028300f Author: Paul Mundt Date: Thu Nov 22 16:29:10 2007 +0900 sh: Get the SH-5 PCI support building. Signed-off-by: Paul Mundt commit ec0898010ff6b8f0b06bb9d7e7e7d2be86cec0ad Author: Paul Mundt Date: Thu Nov 22 16:28:26 2007 +0900 sh: Bump number of quicklists for SH-5. Sync up with the SH definitions. Signed-off-by: Paul Mundt commit fb5f1477b5e651cc7a79b3c5380891a869f63ea2 Author: Paul Mundt Date: Thu Nov 22 13:11:39 2007 +0900 sh: Add SH-5 subtypes to check_bugs() for utsname. Signed-off-by: Paul Mundt commit c6ed81ea18aa3bc13eff5fec3279472043c0659d Author: Paul Mundt Date: Wed Nov 21 23:27:52 2007 +0900 sh: Kill off the rest of arch/sh64/kernel/. Signed-off-by: Paul Mundt commit f529cad64c7ef1e47ddef35c3d805b06db65b4bc Author: Paul Mundt Date: Wed Nov 21 23:16:33 2007 +0900 sh: Get the mach-cayman IRQ support building. Signed-off-by: Paul Mundt commit 4c0a60cca519e4199f050e7d6fee8067d9d44d50 Author: Paul Mundt Date: Wed Nov 21 22:53:34 2007 +0900 sh: Kill off the last of the sh64 headers. Signed-off-by: Paul Mundt commit 5add3a2aa41ed12ee02aa7013db8dc4f1f32c7d8 Author: Paul Mundt Date: Wed Nov 21 22:46:14 2007 +0900 sh: clear/copy_page renames in lib and lib64. Signed-off-by: Paul Mundt commit afa66c530f15b055ec106dabd64153a00dabd4db Author: Paul Mundt Date: Wed Nov 21 22:30:58 2007 +0900 sh: Rename the _32 and _64 TLB flush variants. Signed-off-by: Paul Mundt commit 60c7e4574d07726ebce59ff5d7262f40dc9599cc Author: Paul Mundt Date: Wed Nov 21 22:28:28 2007 +0900 sh: Consolidate sh/sh64 Makefiles. Signed-off-by: Paul Mundt commit 4cb6f2af531ef829fb848009e3b93808e8c88104 Author: Paul Mundt Date: Wed Nov 21 22:13:34 2007 +0900 sh: Tidy up KBUILD_IMAGE for sh64. Signed-off-by: Paul Mundt commit ac5c8ee5c256f202b3ceb9b2ff40ebf3952c47d8 Author: Paul Mundt Date: Wed Nov 21 21:54:07 2007 +0900 sh: Remove duplicate SUPERH64 symbol. Signed-off-by: Paul Mundt commit 4cf85955eae7cd17976977b7065eef2dde23bf72 Author: Paul Mundt Date: Wed Nov 21 18:22:05 2007 +0900 sh: Generic BUG only works for sh32. Signed-off-by: Paul Mundt commit 534faee71d89f4d506b4671415ed0ebc79fd2426 Author: Paul Mundt Date: Wed Nov 21 18:06:34 2007 +0900 sh: Add onchip remap prototypes, kill old sh64 io.h. Signed-off-by: Paul Mundt commit 1dd43f420f7677ec0aadbdabcb3b6d226bdfc605 Author: Paul Mundt Date: Wed Nov 21 17:58:13 2007 +0900 sh: Copy over special CFLAGS for SH-5 TLB miss. Signed-off-by: Paul Mundt commit 5f864afd35bee7efacff187790045df0be357e97 Author: Paul Mundt Date: Wed Nov 21 17:55:12 2007 +0900 sh: Fix up user_fpu_struct typo for SH-5. Signed-off-by: Paul Mundt commit c609a121f183707277805c904aa727137e371994 Author: Paul Mundt Date: Wed Nov 21 17:47:15 2007 +0900 sh: Mark some IRQ debug options sh32 only. Signed-off-by: Paul Mundt commit 5d176d8c37f975e0a03f226146717ac4a985e986 Author: Paul Mundt Date: Wed Nov 21 17:28:37 2007 +0900 sh: Special layout for SH-5 stat.h and user.h. Signed-off-by: Paul Mundt commit 26a083a75a1f8d7a8bd2edcfb9bd6a5d2b061b5d Author: Paul Mundt Date: Wed Nov 21 17:28:09 2007 +0900 sh: Purge dead sh64 headers. Signed-off-by: Paul Mundt commit 6ede090cd2c5c2bbdfb09045dceb870e5da703ca Author: Paul Mundt Date: Wed Nov 21 17:09:14 2007 +0900 sh: Kill off arch/sh64/mm. Signed-off-by: Paul Mundt commit ebbbb2d0644410e20ff913924181c20ae8eb4ef6 Author: Paul Mundt Date: Wed Nov 21 17:07:46 2007 +0900 sh: Fix up proc ASIDs for CPU-local ASID cache accessors. Signed-off-by: Paul Mundt commit 63d2a3fcbb047eac78ae968e837667a7d1ad98c9 Author: Paul Mundt Date: Wed Nov 21 17:07:06 2007 +0900 sh: Move over SH-5 TLB and cache support code. Signed-off-by: Paul Mundt commit 5a9c9c663838744195ad1e3649bb22d29db7c4fc Author: Paul Mundt Date: Wed Nov 21 16:58:56 2007 +0900 sh: Merge sh64 Kconfig.debug options. Signed-off-by: Paul Mundt commit c6e1f3bea82704d1907eb324c613fdd1b8ab67b4 Author: Paul Mundt Date: Wed Nov 21 16:55:27 2007 +0900 sh: Kill off a stray proc tlb reference in fault_64. Signed-off-by: Paul Mundt commit 41103f262015d4dad7d7e2d549e3865970481965 Author: Paul Mundt Date: Wed Nov 21 16:53:37 2007 +0900 sh: Merge the sh64 zImage bits. Signed-off-by: Paul Mundt commit 67225d401a95fad070830c7df9969248efda01a5 Author: Paul Mundt Date: Wed Nov 21 16:19:12 2007 +0900 sh: SH-5 uses a 64-bit PTE_MAGNITUDE, as X2 TLB. Signed-off-by: Paul Mundt commit c832481c42fbe619f96b6ba7d07bc061b63b23b9 Author: Paul Mundt Date: Wed Nov 21 16:04:12 2007 +0900 sh: Use existing CONFIG_CACHE_xx options in head_64.S. Signed-off-by: Paul Mundt commit b1ab639c01c1527444808524e2bc5f02e9fecaff Author: Paul Mundt Date: Wed Nov 21 15:58:24 2007 +0900 sh: Fix up generic BUG build for SH-5. Signed-off-by: Paul Mundt commit 9c64e410b5f714f1be43a715e51cce6f90271161 Author: Paul Mundt Date: Wed Nov 21 15:58:01 2007 +0900 sh: Consolidate Kconfig.sh/Kconfig.sh64. Fold in the sh64-specific bits in to the main Kconfig.sh, and move this back as arch/sh/Kconfig. Signed-off-by: Paul Mundt commit 51431d88278c48b451b40225a0dafcdafcac08c0 Author: Paul Mundt Date: Wed Nov 21 15:46:07 2007 +0900 sh: Bump the MEMORY_SIZE default to something reasonable. Signed-off-by: Paul Mundt commit 107ca7da2e4e0799bbe86909387bb3578733695e Author: Paul Mundt Date: Wed Nov 21 15:43:43 2007 +0900 sh: Kill off some dead sh64 kconfig symbols. Signed-off-by: Paul Mundt commit 03063cfaa8c13307666b27f4219ead6bf4638875 Author: Paul Mundt Date: Wed Nov 21 15:34:33 2007 +0900 sh: Switch SH-5 to use CONFIG_PAGE_OFFSET. Signed-off-by: Paul Mundt commit 36bd708ab6745fe6246c1313eed2f7d0a64002a6 Author: Paul Mundt Date: Wed Nov 21 15:34:02 2007 +0900 sh: Move PXSEG comments to addrspace.h. Signed-off-by: Paul Mundt commit 4c20778e90bbd831d8f5f51bdf2811608217236f Author: Paul Mundt Date: Wed Nov 21 15:23:07 2007 +0900 sh: Set HPAGE_SHIFT for 512MB hugetlb pages. Signed-off-by: Paul Mundt commit bdf580ee4873fec99c450a2d9066ebc9e9a0e67b Author: Paul Mundt Date: Tue Nov 20 18:45:39 2007 +0900 sh: Update cayman defconfig. Signed-off-by: Paul Mundt commit e6f3e0b0c31bbb6894a57c7109a08fb5c654ba9a Author: Paul Mundt Date: Tue Nov 20 18:44:39 2007 +0900 sh: Stubs for fpu disabled on SH-5. Signed-off-by: Paul Mundt commit c1a8d79b762a3d1d72813651a746ebc4f6f70baf Author: Paul Mundt Date: Tue Nov 20 18:33:03 2007 +0900 sh: Stub in CPU subtype setup code for SH5-101/103. Signed-off-by: Paul Mundt commit 6a58874c837bd2a2c1801610ca9d9351cf26138f Author: Paul Mundt Date: Tue Nov 20 18:29:00 2007 +0900 sh: Add the SH-5 cpu type symbolic names. Signed-off-by: Paul Mundt commit e3069318c0b627fe0b96e1585c610eadbe47637a Author: Paul Mundt Date: Tue Nov 20 18:27:20 2007 +0900 sh: Plug in simple SH-5 subtype probing. Signed-off-by: Paul Mundt commit 0a12daae310c83ea27df9f7524fa4a4daaf77117 Author: Paul Mundt Date: Tue Nov 20 18:26:54 2007 +0900 sh: Kill off do_NMI stub in SH-5 ex table. Signed-off-by: Paul Mundt commit b434f7363df184e8cf53672a1808a555f75d7edc Author: Paul Mundt Date: Tue Nov 20 18:26:28 2007 +0900 sh: Move quad-word real-address I/O defs to io.h. Signed-off-by: Paul Mundt commit 61b28a6f1cd559fba54e226d58ce0dc827a2f075 Author: Paul Mundt Date: Tue Nov 20 18:08:06 2007 +0900 sh: Share bug/debug traps across _32 and _64. Signed-off-by: Paul Mundt commit 417192bcb2627513448870b9ea79d71332fb430a Author: Paul Mundt Date: Tue Nov 20 17:01:55 2007 +0900 sh: Move in the SH-5 TLB miss. Signed-off-by: Paul Mundt commit 8450e5e73aeb84286774c63f2b5a9518147e54d9 Author: Paul Mundt Date: Tue Nov 20 16:51:28 2007 +0900 sh: Tidy up various clear_page()/copy_page() definitions. Signed-off-by: Paul Mundt commit 308ca6037e4b60b8e367f808439d86f6b1fd8441 Author: Paul Mundt Date: Tue Nov 20 15:50:59 2007 +0900 sh: sys_sh consolidation for arch_get_unmapped_area(). Signed-off-by: Paul Mundt commit 83d75c82cdb9764fdd3d825917e1c2c6db1906eb Author: Paul Mundt Date: Tue Nov 20 15:48:39 2007 +0900 sh: Share the ELF dump_task interfaces. Signed-off-by: Paul Mundt commit 697bf98e1f0b429e26d741710a577b974f51e7a8 Author: Paul Mundt Date: Tue Nov 20 15:38:50 2007 +0900 sh: Kill off SH-5 enter_deep_standby() cruft. Signed-off-by: Paul Mundt commit 3c152522cc7074a0c1fba21babe15dc124ad60e3 Author: Paul Mundt Date: Tue Nov 20 15:38:11 2007 +0900 sh: Fix up the _stext references for SH-5. Signed-off-by: Paul Mundt commit 4d4477eb24e26806603aa8bf301436b155bc2da0 Author: Paul Mundt Date: Tue Nov 20 15:35:42 2007 +0900 sh: Sync up the _64 linker script with the _32 version. Signed-off-by: Paul Mundt commit 5f42ba0aa628a0fbf9691a2a8c2cbea8ba9b0ee8 Author: Paul Mundt Date: Tue Nov 20 15:16:25 2007 +0900 sh: Merge sh and sh64 module.c. This is trivial, in that they're both effectively the same for the base relocations anyways. SH-5 doesn't need the unaligned bits, and has a few extra relocations, which are never hit on non-SH5 parts. Signed-off-by: Paul Mundt commit 3b805597e0a1c71de84cbc86df6f68c38e24a60b Author: Paul Mundt Date: Tue Nov 20 15:14:48 2007 +0900 sh: ioremap_64 needs after_bootmem. Signed-off-by: Paul Mundt commit 078ee340cf95ec4d7bd03d53efbdbcbfc5758f06 Author: Paul Mundt Date: Tue Nov 20 15:14:31 2007 +0900 sh: Plug in the SHmedia ELF relocations. Signed-off-by: Paul Mundt commit 1a74ae9aefe9a964fd8a035935de5784fd5a667a Author: Paul Mundt Date: Tue Nov 20 14:49:36 2007 +0900 sh: Tidy up lib64 udelay impl. Signed-off-by: Paul Mundt commit 8d2fabc1bfe758671c2cc141a0f07c169a421ba5 Author: Paul Mundt Date: Mon Nov 19 19:13:38 2007 +0900 sh: Move over and enable FPU support for SH-5. Signed-off-by: Paul Mundt commit 83648b9e30e986225284e8b4da3148d8960365f9 Author: Paul Mundt Date: Mon Nov 19 19:08:49 2007 +0900 sh: Common swapper_pg_dir usage for SH-5. Signed-off-by: Paul Mundt commit ea3bbbb9acfa5b173a22b558e40ec646811b60c6 Author: Paul Mundt Date: Mon Nov 19 19:07:51 2007 +0900 sh: Provide dummy swapper pt_regs for SH-5 ctx switch. Signed-off-by: Paul Mundt commit 0cfcd96434459cfeb97f03f5ab72d2b97a085e0c Author: Paul Mundt Date: Mon Nov 19 19:00:41 2007 +0900 sh: Move over sh64 switch_to and stack unwinder. Signed-off-by: Paul Mundt commit fbca96ed8e75084523dde5fc3b9e2039dc4cc1a2 Author: Paul Mundt Date: Mon Nov 19 18:57:03 2007 +0900 sh: Split out tlb-flush in to _32 and _64 variants. Signed-off-by: Paul Mundt commit bd85be6a142ef11296481fe981c9d32e25a58e82 Author: Paul Mundt Date: Mon Nov 19 18:26:19 2007 +0900 sh: Split out pgtable.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit cbdd14a6477501640b5d4746c3c989d02b58bbb2 Author: Paul Mundt Date: Mon Nov 19 14:26:09 2007 +0900 sh: ioremap_64 needs proc_fs.h. Signed-off-by: Paul Mundt commit 60e76e13261894aa56acd81cb4ca5e5cfc01dcfb Author: Paul Mundt Date: Sun Nov 11 18:43:33 2007 +0900 sh: Split out ioremap in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 7565078fe1dd91509717d6aca1e3993d5bb09bbf Author: Paul Mundt Date: Sun Nov 11 18:22:55 2007 +0900 sh: Split out sh_ksyms.c in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 0f047418fa9447db515d3aa00eec5ee51cb851ac Author: Paul Mundt Date: Sun Nov 11 18:11:18 2007 +0900 sh: Move over the SH-5 entry.S. Signed-off-by: Paul Mundt commit 185d3baa8d04e120164f451914622c51d071a87c Author: Paul Mundt Date: Sun Nov 11 17:58:11 2007 +0900 sh: Split out linker script to _32 and _64 variants. Signed-off-by: Paul Mundt commit 1d9e7901ffdf820b2f6e79e7345fa36e8218a41e Author: Paul Mundt Date: Sun Nov 11 17:46:49 2007 +0900 sh: Split out syscall ABI for _32 and _64 variants. Signed-off-by: Paul Mundt commit 946a698863e1e49efbca57ad7fc63f6d0adc60c6 Author: Paul Mundt Date: Sun Nov 11 17:41:56 2007 +0900 sh: Fix up the head-y targets for _32 and _64. Signed-off-by: Paul Mundt commit e99d246cec45bd3b8f0636e148b904055a2bb497 Author: Paul Mundt Date: Sun Nov 11 17:41:35 2007 +0900 sh: Fix up header reference for arch/sh/lib64/panic.c. Signed-off-by: Paul Mundt commit ea8e2e223c7745a2bdc3cca5d3ba5d78284c015e Author: Paul Mundt Date: Sun Nov 11 17:37:21 2007 +0900 sh: Kill off lib64 version of iomap wrappers. Signed-off-by: Paul Mundt commit ef1f7d79895b6ebcfea84bb24e9a3057532513df Author: Paul Mundt Date: Sun Nov 11 17:36:13 2007 +0900 sh: Split out checksum.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 71adf0370c622c6cfd3cd82fa1ed49b2240b6db6 Author: Paul Mundt Date: Sun Nov 11 17:28:18 2007 +0900 sh: Plug in SH-5 ffz()/__ffs() bitops. Signed-off-by: Paul Mundt commit 31f1660eb1c59df44092968fe138fd17033d7b23 Author: Paul Mundt Date: Sun Nov 11 17:25:10 2007 +0900 sh: Fix up 64kB page size selection on SH-5. Signed-off-by: Paul Mundt commit 6827c7d596679e4ce468e76684afad917a37c8c6 Author: Paul Mundt Date: Sun Nov 11 17:24:50 2007 +0900 sh: Split out extable.c _32 and _64 variants. Signed-off-by: Paul Mundt commit 868d2f466fe0f6d71cc6240f7863b13f3d9113cc Author: Paul Mundt Date: Sun Nov 11 17:07:06 2007 +0900 sh: Add SH-5 support to the consistent DMA impl. Signed-off-by: Paul Mundt commit a0ba5a8ab301f01a05497547d4d1f03752dd4370 Author: Paul Mundt Date: Sun Nov 11 15:53:51 2007 +0900 sh: flush_cache_sigtramp() takes 1 arg only. Signed-off-by: Paul Mundt commit 0453aab55db2ba63249200bcdb132b1dac608dee Author: Paul Mundt Date: Sat Nov 10 20:39:56 2007 +0900 sh: Move vsyscall_init() defs up one level. Signed-off-by: Paul Mundt commit ab5544a551ace5681d7673a84ba97712c7129f5c Author: Paul Mundt Date: Sat Nov 10 20:39:32 2007 +0900 sh: Nopped out p3_cache_init() on SH-5 also. Signed-off-by: Paul Mundt commit f25ce8de1c24c00b8a3f9d1a4a0fd5822a862354 Author: Paul Mundt Date: Sat Nov 10 20:39:06 2007 +0900 sh: Fix up VMALLOC_START for SH-5. Signed-off-by: Paul Mundt commit 1087aba7ef71382529f8e7dd2f7546e7ebddd831 Author: Paul Mundt Date: Sat Nov 10 20:35:53 2007 +0900 sh: Move over the SH-5 head.S and tlb.h. Signed-off-by: Paul Mundt commit b9919da809e14759d02bef9222b122fbe3fc3b95 Author: Paul Mundt Date: Sat Nov 10 20:27:03 2007 +0900 sh: Have SH-5 provide an {en,dis}able_fpu() impl. Signed-off-by: Paul Mundt commit 378a9db91d257a49f29fa7d7686ead6bd30dcce3 Author: Paul Mundt Date: Sat Nov 10 20:25:28 2007 +0900 sh: Disable initial cache flush on SH-5. Signed-off-by: Paul Mundt commit 2e14c4bc845f17f2fbdffb8f226c695e6bd87835 Author: Paul Mundt Date: Sat Nov 10 20:18:18 2007 +0900 sh: Don't reference UBC code in CPU init on sh64. Signed-off-by: Paul Mundt commit 4be5163a64deee8092c9e34c382db60f13f5454b Author: Paul Mundt Date: Sat Nov 10 20:15:31 2007 +0900 sh: imask IRQ depends on sh32. Signed-off-by: Paul Mundt commit 66a4e6b0a8eb6da3c36ebe4aec70cd3232977eaa Author: Paul Mundt Date: Sat Nov 10 20:14:15 2007 +0900 sh: Move in the SH-5 traps.c impl. Signed-off-by: Paul Mundt commit e44fb4130349503b63dc42824ca0a812aa0bd1fd Author: Paul Mundt Date: Sat Nov 10 20:12:25 2007 +0900 sh: timer.h stub for SH-5. Signed-off-by: Paul Mundt commit ee38bf7bd11c55aa9ec426b46d8e20b73f063b8a Author: Paul Mundt Date: Sat Nov 10 20:12:01 2007 +0900 sh: Move arch/sh64/kernel/sys_sh64.c to arch/sh/kernel/ Signed-off-by: Paul Mundt commit 178eba3d98ebd3d158b99b3700da2caf4f61904f Author: Paul Mundt Date: Sat Nov 10 20:07:57 2007 +0900 sh: Move in the SH-5 signal trampoline impl. Signed-off-by: Paul Mundt commit 5ef91fbca0d8eeb7dcf958530dddf2b133188682 Author: Paul Mundt Date: Sat Nov 10 20:01:51 2007 +0900 sh: More SH-5 cpuinfo tidying. Signed-off-by: Paul Mundt commit 2eca468a18fe244e99db6ca6a98aed83d81da1c5 Author: Paul Mundt Date: Sat Nov 10 19:57:58 2007 +0900 sh: Consolidate slab/kmalloc minalign values. Signed-off-by: Paul Mundt commit f5214dda9f986f8997e2ebc36d7bcecffaa207bc Author: Paul Mundt Date: Sat Nov 10 19:55:50 2007 +0900 sh: Split out uaccess.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 25e87bbd0404198c8752ebd9ea161cfcecb6207f Author: Paul Mundt Date: Sat Nov 10 19:54:16 2007 +0900 sh: SH-5 also uses the ASID cache. Signed-off-by: Paul Mundt commit 42ae78dbfc2edf9680c385ed775b3e526be2f7d6 Author: Paul Mundt Date: Sat Nov 10 19:53:31 2007 +0900 sh: Move in the SH-5 ptrace impl. Signed-off-by: Paul Mundt commit f5045f97281f2468a06fc53771f0664dc6410837 Author: Paul Mundt Date: Sat Nov 10 19:46:31 2007 +0900 sh: Split out system.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 50ee21fbb7900f0b9ad0e878cb139daf7d491d0a Author: Paul Mundt Date: Sat Nov 10 19:16:55 2007 +0900 sh: Split out 29-bit and 32-bit physical mode definitions. Signed-off-by: Paul Mundt commit e8e0b53b75c0b908772c0074cbfc0b68cae300bf Author: Paul Mundt Date: Fri Nov 9 17:08:54 2007 +0900 sh: Split out processor.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit e900a66e98c1680d4d178f0a23481c635c0217fd Author: Paul Mundt Date: Fri Nov 9 16:57:27 2007 +0900 sh: SH-5 pt_regs. Signed-off-by: Paul Mundt commit 52a8b651a0ea62c50d6938e2c9e32047cd7a6591 Author: Paul Mundt Date: Fri Nov 9 16:57:04 2007 +0900 sh: Split out arch/sh/kernel/process.c for _32 and _64 variants. Signed-off-by: Paul Mundt commit 12db0f7353d052dbdfc22f3bcdc6cdd3a195da24 Author: Paul Mundt Date: Fri Nov 9 16:40:43 2007 +0900 sh: Have 32-bit use arch/sh/kernel/Makefile_32. Signed-off-by: Paul Mundt commit 8e4d1313e07a42ca115c7506a2ea95c9914b9ba2 Author: Paul Mundt Date: Fri Nov 9 16:37:18 2007 +0900 sh: Move in the SH-5 mmu_context headers. Signed-off-by: Paul Mundt commit 4c2b6f660281cb91f25d3bab6a2bc7a7f492f685 Author: Paul Mundt Date: Fri Nov 9 14:07:56 2007 +0900 sh: Kill off lib64 version of io.c. Signed-off-by: Paul Mundt commit c9cb361acd73ba98d2354dac384fe110602c254e Author: Paul Mundt Date: Fri Nov 9 14:06:24 2007 +0900 sh: Move sh32 optimized I/O routines to arch/sh/lib/ Signed-off-by: Paul Mundt commit cac6540c5e5dc1212d21172be3aa12cf3a5a114c Author: Paul Mundt Date: Fri Nov 9 13:58:44 2007 +0900 sh: SH-5 byteorder routines. Signed-off-by: Paul Mundt commit 4bd454c9564435367f9f00baeb68220c7f0ba25d Author: Paul Mundt Date: Fri Nov 9 13:45:42 2007 +0900 sh: Consolidate CPU features in Kconfig.cpu. Signed-off-by: Paul Mundt commit e2dea31a8d3cca600c2af8b18ccbf9a36deb0b65 Author: Paul Mundt Date: Fri Nov 9 13:40:50 2007 +0900 sh: SH-5 version of current_thread_info(). Signed-off-by: Paul Mundt commit 2a8a15b7874120206e08836946a0500929c0ba95 Author: Paul Mundt Date: Fri Nov 9 13:34:36 2007 +0900 sh: Split out irqflags.h in to _32 and _64 variants. Signed-off-by: Paul Mundt commit 351c3be0341eb40e725581d8cf60b87ac3e80193 Author: Paul Mundt Date: Fri Nov 9 13:00:30 2007 +0900 sh: Split out asm/string.h for sh32 and sh64. Signed-off-by: Paul Mundt commit 1eac647e215a42d8c54a068c312328f22fa854ad Author: Paul Mundt Date: Fri Nov 9 12:58:12 2007 +0900 sh: Add SH-5 support to io.h. Signed-off-by: Paul Mundt commit fe9feddd4fd38d96ac688c1db14ee458c62d5c32 Author: Paul Mundt Date: Fri Nov 9 12:56:06 2007 +0900 sh: Add in cacheflush and DMA headers for SH-5. Signed-off-by: Paul Mundt commit a65352f69343901c2da85e6ba960605646de00ca Author: Paul Mundt Date: Thu Nov 8 19:24:00 2007 +0900 sh64: Kill off arch/sh64/oprofile. The same implementation exists in arch/sh/oprofile, so get rid of this version. Signed-off-by: Paul Mundt commit f3bb964dc89fd3fa002d6e15373257c19c6709e4 Author: Paul Mundt Date: Thu Nov 8 19:22:26 2007 +0900 sh: Move sh64 board defconfigs to arch/sh/configs. Signed-off-by: Paul Mundt commit 706597cd57ed115ca48d7ecde33ed119c0e9ee70 Author: Paul Mundt Date: Thu Nov 8 19:21:50 2007 +0900 sh: Move sh64 boards to arch/sh/. Signed-off-by: Paul Mundt commit 64119cecb64e1cc49eb7f43c90487b4e78969bfc Author: Paul Mundt Date: Thu Nov 8 19:08:28 2007 +0900 sh: Correct SH-5 instruction size value. Signed-off-by: Paul Mundt commit 9f60670f65ae9369db4c738ab18ff1d1cc15268d Author: Paul Mundt Date: Thu Nov 8 19:00:27 2007 +0900 sh: Add cache definitions for SH-5. Signed-off-by: Paul Mundt commit 04ef569b3dd14f115f8f1ce7a9fb873efc46ea8d Author: Paul Mundt Date: Thu Nov 8 18:58:52 2007 +0900 sh: Add addrspace.h segmentation stub for SH-5. Signed-off-by: Paul Mundt commit 0a59cfea464567064269f1186d374abb70e7e4d0 Author: Paul Mundt Date: Thu Nov 8 18:58:00 2007 +0900 sh: BUGFLAG_WARNING needs GENERIC_BUG. Move the HAVE_ARCH_BUG/HAVE_ARCH_WARN_ON definitions underneath CONFIG_GENERIC_BUG. This is needed for BUGFLAG_WARNING usage. Signed-off-by: Paul Mundt commit ede9f423bfe59aed3beb1511fb9a10b4f0a23878 Author: Paul Mundt Date: Thu Nov 8 18:55:39 2007 +0900 sh: Fix up fixmap location for SH-5. Signed-off-by: Paul Mundt commit e56b575a99d81488bf8e8589a95b9b1b4502f805 Author: Paul Mundt Date: Thu Nov 8 18:54:58 2007 +0900 sh: Add SH-5 support to asm/module.h. Signed-off-by: Paul Mundt commit 233a028bf80d971c6f8ede33b2c7c451e307e33c Author: Paul Mundt Date: Thu Nov 8 18:54:16 2007 +0900 sh: Switch Kconfig.sh64 to use arch/sh/mm/Kconfig. Consolidates the HUGETLB definitions and others. Signed-off-by: Paul Mundt commit 77908b59c14b83b37009cba31736a545f77253e7 Author: Paul Mundt Date: Thu Nov 8 18:52:35 2007 +0900 sh: Plug SH-5 in to arch/sh/Makefile. Adds the ISA tuning and a lib64 rule. Signed-off-by: Paul Mundt commit 7f6ef0fa9c425de227469f4794c7ec41cbd78484 Author: Paul Mundt Date: Thu Nov 8 18:51:33 2007 +0900 sh: Move arch/sh64/lib to arch/sh/lib64. Signed-off-by: Paul Mundt commit c388a04054796243a0edd6a2478819ab4c526d6f Author: Paul Mundt Date: Thu Nov 8 18:46:51 2007 +0900 sh: Move the sh64 Kconfig to arch/sh/Kconfig.sh64. Signed-off-by: Paul Mundt commit 77fd75b7ffb66b6055fbc213dcfaa3d7c316349c Author: Paul Mundt Date: Thu Nov 8 18:44:09 2007 +0900 sh: Split out cache status bits per-CPU family. Signed-off-by: Paul Mundt commit d284847d63579b25ae2fd084730841a3f33c36ba Author: Paul Mundt Date: Thu Nov 8 18:42:46 2007 +0900 sh: Split out PXSEG segmentation per-CPU family. The CPU family abstraction already exists, so move out the PXSEG definition for each one. SH-2A already has this special cased, and SH-5 will as well. Signed-off-by: Paul Mundt commit 81bb06f66d1d5f2a8b2cec07c20d8a986d1573e6 Author: Paul Mundt Date: Thu Nov 8 18:39:33 2007 +0900 sh: Add a SUPERH32 config symbol. We need to differentiate from SUPERH64, so add a SUPERH32 for regular sh. Signed-off-by: Paul Mundt commit ef68728f7c5cfccc10e316ade5047dea831bd902 Author: Paul Mundt Date: Thu Nov 8 18:38:14 2007 +0900 sh: Move CPU subtypes to Kconfig.sh. We intend to share the mm options, so move the SH-only subtypes up a level. Signed-off-by: Paul Mundt commit 5d49dd8cd14f8d7a0d0ad9fe4cc9d3d87a1ff74e Author: Paul Mundt Date: Thu Nov 8 18:30:40 2007 +0900 sh: Rename Kconfig to Kconfig.sh. Signed-off-by: Paul Mundt commit ff565107a7edbcaa717ee98ef07df4d90fb16aff Author: Paul Mundt Date: Thu Nov 8 14:45:55 2007 +0900 sh64: Use the generic rtc-sh driver. Rip out the sh64-specific RTC bits, use rtc-sh instead. Signed-off-by: Paul Mundt commit 95c73ff0c56c4d12d732afd4308c318db767530e Author: Paul Mundt Date: Thu Nov 8 14:44:44 2007 +0900 rtc: rtc-sh: SH-5 support. Trivial support for the SH-5 (sh64) on-chip RTC. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton --- Makefile | 2 arch/sh/Kconfig | 353 ++- arch/sh/Kconfig.cpu | 115 + arch/sh/Kconfig.debug | 47 arch/sh/Makefile | 98 - arch/sh/boards/cayman/Makefile | 5 arch/sh/boards/cayman/irq.c | 197 ++ arch/sh/boards/cayman/led.c | 51 arch/sh/boards/cayman/setup.c | 187 + arch/sh/boards/dreamcast/irq.c | 2 arch/sh/boot/Makefile | 18 arch/sh/boot/compressed/Makefile | 46 arch/sh/boot/compressed/Makefile_32 | 43 arch/sh/boot/compressed/Makefile_64 | 45 arch/sh/boot/compressed/cache.c | 12 arch/sh/boot/compressed/head.S | 120 - arch/sh/boot/compressed/head_32.S | 120 + arch/sh/boot/compressed/head_64.S | 163 + arch/sh/boot/compressed/misc.c | 241 -- arch/sh/boot/compressed/misc_32.c | 244 ++ arch/sh/boot/compressed/misc_64.c | 250 ++ arch/sh/boot/compressed/vmlinux_64.lds | 64 arch/sh/configs/cayman_defconfig | 1166 ++++++++++++ arch/sh/configs/r7785rp_defconfig | 13 arch/sh/drivers/pci/Makefile | 2 arch/sh/drivers/pci/ops-cayman.c | 94 arch/sh/drivers/pci/ops-sh5.c | 93 arch/sh/drivers/pci/pci-sh5.c | 228 ++ arch/sh/drivers/pci/pci-sh5.h | 113 + arch/sh/drivers/pci/pci.c | 2 arch/sh/kernel/Makefile | 30 arch/sh/kernel/Makefile_32 | 26 arch/sh/kernel/Makefile_64 | 22 arch/sh/kernel/cpu/Makefile | 6 arch/sh/kernel/cpu/init.c | 74 arch/sh/kernel/cpu/irq/Makefile | 4 arch/sh/kernel/cpu/irq/intc-sh5.c | 257 ++ arch/sh/kernel/cpu/sh2/entry.S | 19 arch/sh/kernel/cpu/sh2a/Makefile | 4 arch/sh/kernel/cpu/sh2a/clock-sh7203.c | 89 arch/sh/kernel/cpu/sh2a/fpu.c | 633 ++++++ arch/sh/kernel/cpu/sh2a/probe.c | 22 arch/sh/kernel/cpu/sh2a/setup-sh7203.c | 319 +++ arch/sh/kernel/cpu/sh3/entry.S | 24 arch/sh/kernel/cpu/sh3/ex.S | 2 arch/sh/kernel/cpu/sh3/probe.c | 6 arch/sh/kernel/cpu/sh4/Makefile | 2 arch/sh/kernel/cpu/sh4/fpu.c | 533 +++-- arch/sh/kernel/cpu/sh4/softfloat.c | 892 +++++++++ arch/sh/kernel/cpu/sh5/Makefile | 7 arch/sh/kernel/cpu/sh5/entry.S | 2101 +++++++++++++++++++++ arch/sh/kernel/cpu/sh5/fpu.c | 166 + arch/sh/kernel/cpu/sh5/probe.c | 76 arch/sh/kernel/cpu/sh5/switchto.S | 198 ++ arch/sh/kernel/cpu/sh5/unwind.c | 326 +++ arch/sh/kernel/dump_task.c | 31 arch/sh/kernel/entry-common.S | 27 arch/sh/kernel/head.S | 120 - arch/sh/kernel/head_32.S | 124 + arch/sh/kernel/head_64.S | 356 +++ arch/sh/kernel/init_task.c | 4 arch/sh/kernel/io.c | 67 arch/sh/kernel/module.c | 62 arch/sh/kernel/process.c | 558 ----- arch/sh/kernel/process_32.c | 465 ++++ arch/sh/kernel/process_64.c | 701 +++++++ arch/sh/kernel/ptrace.c | 274 -- arch/sh/kernel/ptrace_32.c | 287 +++ arch/sh/kernel/ptrace_64.c | 341 +++ arch/sh/kernel/setup.c | 23 arch/sh/kernel/sh_ksyms.c | 150 - arch/sh/kernel/sh_ksyms_32.c | 150 + arch/sh/kernel/sh_ksyms_64.c | 55 arch/sh/kernel/signal.c | 629 ------ arch/sh/kernel/signal_32.c | 611 ++++++ arch/sh/kernel/signal_64.c | 751 +++++++ arch/sh/kernel/sys_sh.c | 100 - arch/sh/kernel/sys_sh32.c | 84 arch/sh/kernel/sys_sh64.c | 66 arch/sh/kernel/syscalls.S | 343 --- arch/sh/kernel/syscalls_32.S | 343 +++ arch/sh/kernel/syscalls_64.S | 381 +++ arch/sh/kernel/time.c | 269 -- arch/sh/kernel/time_32.c | 269 ++ arch/sh/kernel/time_64.c | 519 +++++ arch/sh/kernel/timers/timer-cmt.c | 4 arch/sh/kernel/traps.c | 949 --------- arch/sh/kernel/traps_32.c | 919 +++++++++ arch/sh/kernel/traps_64.c | 975 ++++++++++ arch/sh/kernel/vmlinux.lds.S | 139 - arch/sh/kernel/vmlinux_32.lds.S | 152 + arch/sh/kernel/vmlinux_64.lds.S | 164 + arch/sh/lib/Makefile | 5 arch/sh/lib/clear_page.S | 154 + arch/sh/lib/copy_page.S | 389 ++++ arch/sh/lib/io.c | 82 arch/sh/lib64/.gitignore | 1 arch/sh/lib64/Makefile | 15 arch/sh/lib64/c-checksum.c | 214 ++ arch/sh/lib64/clear_page.S | 54 arch/sh/lib64/copy_page.S | 89 arch/sh/lib64/copy_user_memcpy.S | 217 ++ arch/sh/lib64/dbg.c | 430 ++++ arch/sh/lib64/memcpy.c | 81 arch/sh/lib64/panic.c | 58 arch/sh/lib64/udelay.c | 56 arch/sh/mm/Kconfig | 222 -- arch/sh/mm/Makefile | 40 arch/sh/mm/Makefile_32 | 36 arch/sh/mm/Makefile_64 | 44 arch/sh/mm/cache-debugfs.c | 9 arch/sh/mm/cache-sh4.c | 14 arch/sh/mm/cache-sh5.c | 1029 ++++++++++ arch/sh/mm/cache-sh7705.c | 12 arch/sh/mm/clear_page.S | 152 - arch/sh/mm/consistent.c | 46 arch/sh/mm/copy_page.S | 388 ---- arch/sh/mm/extable.c | 21 arch/sh/mm/extable_32.c | 21 arch/sh/mm/extable_64.c | 82 arch/sh/mm/fault.c | 303 --- arch/sh/mm/fault_32.c | 303 +++ arch/sh/mm/fault_64.c | 275 ++ arch/sh/mm/init.c | 68 arch/sh/mm/ioremap.c | 150 - arch/sh/mm/ioremap_32.c | 150 + arch/sh/mm/ioremap_64.c | 404 ++++ arch/sh/mm/pg-nommu.c | 4 arch/sh/mm/pmb.c | 26 arch/sh/mm/tlb-flush.c | 140 - arch/sh/mm/tlb-nommu.c | 10 arch/sh/mm/tlb-sh4.c | 7 arch/sh/mm/tlb-sh5.c | 164 + arch/sh/mm/tlbflush_32.c | 140 + arch/sh/mm/tlbflush_64.c | 475 ++++ arch/sh/tools/mach-types | 1 arch/sh64/Kconfig | 290 --- arch/sh64/Kconfig.debug | 33 arch/sh64/Makefile | 111 - arch/sh64/boot/Makefile | 20 arch/sh64/boot/compressed/Makefile | 46 arch/sh64/boot/compressed/cache.c | 39 arch/sh64/boot/compressed/head.S | 164 - arch/sh64/boot/compressed/install.sh | 56 arch/sh64/boot/compressed/misc.c | 250 -- arch/sh64/boot/compressed/vmlinux.lds.S | 64 arch/sh64/configs/cayman_defconfig | 1126 ----------- arch/sh64/configs/harp_defconfig | 745 ------- arch/sh64/configs/sim_defconfig | 558 ----- arch/sh64/kernel/Makefile | 36 arch/sh64/kernel/alphanum.c | 43 arch/sh64/kernel/asm-offsets.c | 33 arch/sh64/kernel/dma.c | 297 --- arch/sh64/kernel/early_printk.c | 99 - arch/sh64/kernel/entry.S | 2102 ---------------------- arch/sh64/kernel/fpu.c | 170 - arch/sh64/kernel/head.S | 372 --- arch/sh64/kernel/init_task.c | 46 arch/sh64/kernel/irq.c | 115 - arch/sh64/kernel/irq_intc.c | 272 -- arch/sh64/kernel/led.c | 40 arch/sh64/kernel/module.c | 161 - arch/sh64/kernel/pci_sh5.c | 536 ----- arch/sh64/kernel/pci_sh5.h | 107 - arch/sh64/kernel/pcibios.c | 168 - arch/sh64/kernel/process.c | 691 ------- arch/sh64/kernel/ptrace.c | 332 --- arch/sh64/kernel/semaphore.c | 140 - arch/sh64/kernel/setup.c | 379 --- arch/sh64/kernel/sh_ksyms.c | 62 arch/sh64/kernel/signal.c | 750 ------- arch/sh64/kernel/switchto.S | 198 -- arch/sh64/kernel/sys_sh64.c | 304 --- arch/sh64/kernel/syscalls.S | 381 --- arch/sh64/kernel/time.c | 593 ------ arch/sh64/kernel/traps.c | 982 ---------- arch/sh64/kernel/unwind.c | 326 --- arch/sh64/kernel/vmlinux.lds.S | 140 - arch/sh64/lib/.gitignore | 1 arch/sh64/lib/Makefile | 19 arch/sh64/lib/c-checksum.c | 217 -- arch/sh64/lib/copy_user_memcpy.S | 217 -- arch/sh64/lib/dbg.c | 430 ---- arch/sh64/lib/io.c | 128 - arch/sh64/lib/iomap.c | 54 arch/sh64/lib/memcpy.c | 81 arch/sh64/lib/page_clear.S | 54 arch/sh64/lib/page_copy.S | 91 arch/sh64/lib/panic.c | 58 arch/sh64/lib/udelay.c | 59 arch/sh64/mach-cayman/Makefile | 11 arch/sh64/mach-cayman/iomap.c | 22 arch/sh64/mach-cayman/irq.c | 195 -- arch/sh64/mach-cayman/led.c | 51 arch/sh64/mach-cayman/setup.c | 239 -- arch/sh64/mach-harp/Makefile | 1 arch/sh64/mach-harp/setup.c | 129 - arch/sh64/mach-sim/Makefile | 1 arch/sh64/mach-sim/setup.c | 126 - arch/sh64/mm/Makefile | 44 arch/sh64/mm/cache.c | 1032 ---------- arch/sh64/mm/consistent.c | 53 arch/sh64/mm/extable.c | 80 arch/sh64/mm/fault.c | 602 ------ arch/sh64/mm/hugetlbpage.c | 105 - arch/sh64/mm/init.c | 189 - arch/sh64/mm/ioremap.c | 388 ---- arch/sh64/mm/tlb.c | 166 - arch/sh64/mm/tlbmiss.c | 279 -- arch/sh64/oprofile/Makefile | 12 arch/sh64/oprofile/op_model_null.c | 23 drivers/rtc/Kconfig | 2 drivers/rtc/rtc-sh.c | 24 drivers/serial/sh-sci.h | 8 include/asm-sh/addrspace.h | 43 include/asm-sh/atomic-grb.h | 169 + include/asm-sh/atomic.h | 10 include/asm-sh/auxvec.h | 18 include/asm-sh/bitops-grb.h | 169 + include/asm-sh/bitops-irq.h | 91 include/asm-sh/bitops.h | 117 - include/asm-sh/bug.h | 9 include/asm-sh/bugs.h | 15 include/asm-sh/byteorder.h | 45 include/asm-sh/cache.h | 5 include/asm-sh/checksum.h | 216 -- include/asm-sh/checksum_32.h | 215 ++ include/asm-sh/checksum_64.h | 78 include/asm-sh/cmpxchg-grb.h | 70 include/asm-sh/cmpxchg-irq.h | 40 include/asm-sh/cpu-sh2/addrspace.h | 7 include/asm-sh/cpu-sh2/cache.h | 8 include/asm-sh/cpu-sh2/rtc.h | 8 include/asm-sh/cpu-sh2a/addrspace.h | 11 include/asm-sh/cpu-sh2a/cache.h | 11 include/asm-sh/cpu-sh2a/freq.h | 2 include/asm-sh/cpu-sh2a/rtc.h | 8 include/asm-sh/cpu-sh3/addrspace.h | 7 include/asm-sh/cpu-sh3/cache.h | 5 include/asm-sh/cpu-sh3/rtc.h | 8 include/asm-sh/cpu-sh4/addrspace.h | 6 include/asm-sh/cpu-sh4/cache.h | 5 include/asm-sh/cpu-sh4/fpu.h | 32 include/asm-sh/cpu-sh4/mmu_context.h | 10 include/asm-sh/cpu-sh4/rtc.h | 8 include/asm-sh/cpu-sh5/addrspace.h | 11 include/asm-sh/cpu-sh5/cache.h | 97 + include/asm-sh/cpu-sh5/cacheflush.h | 35 include/asm-sh/cpu-sh5/dma.h | 6 include/asm-sh/cpu-sh5/irq.h | 117 + include/asm-sh/cpu-sh5/mmu_context.h | 27 include/asm-sh/cpu-sh5/registers.h | 106 + include/asm-sh/cpu-sh5/rtc.h | 8 include/asm-sh/cpu-sh5/timer.h | 4 include/asm-sh/delay.h | 8 include/asm-sh/dma-mapping.h | 4 include/asm-sh/elf.h | 75 include/asm-sh/fixmap.h | 5 include/asm-sh/flat.h | 2 include/asm-sh/fpu.h | 46 include/asm-sh/hd64461.h | 28 include/asm-sh/io.h | 70 include/asm-sh/irqflags.h | 97 - include/asm-sh/irqflags_32.h | 99 + include/asm-sh/irqflags_64.h | 85 include/asm-sh/microdev.h | 4 include/asm-sh/mmu_context.h | 87 include/asm-sh/mmu_context_32.h | 47 include/asm-sh/mmu_context_64.h | 75 include/asm-sh/module.h | 4 include/asm-sh/page.h | 102 - include/asm-sh/param.h | 6 include/asm-sh/pci.h | 5 include/asm-sh/pgtable.h | 518 ----- include/asm-sh/pgtable_32.h | 474 ++++ include/asm-sh/pgtable_64.h | 299 +++ include/asm-sh/processor.h | 256 -- include/asm-sh/processor_32.h | 215 ++ include/asm-sh/processor_64.h | 275 ++ include/asm-sh/ptrace.h | 28 include/asm-sh/rtc.h | 2 include/asm-sh/scatterlist.h | 2 include/asm-sh/sections.h | 1 include/asm-sh/sigcontext.h | 16 include/asm-sh/stat.h | 63 include/asm-sh/string.h | 136 - include/asm-sh/string_32.h | 131 + include/asm-sh/string_64.h | 17 include/asm-sh/system.h | 173 - include/asm-sh/system_32.h | 99 + include/asm-sh/system_64.h | 40 include/asm-sh/thread_info.h | 8 include/asm-sh/tlb.h | 10 include/asm-sh/tlb_64.h | 69 include/asm-sh/types.h | 6 include/asm-sh/uaccess.h | 576 ------ include/asm-sh/uaccess_32.h | 518 +++++ include/asm-sh/uaccess_64.h | 302 +++ include/asm-sh/unistd.h | 379 --- include/asm-sh/unistd_32.h | 376 +++ include/asm-sh/unistd_64.h | 415 ++++ include/asm-sh/user.h | 7 include/asm-sh/voyagergx.h | 2 include/asm-sh64/Kbuild | 1 include/asm-sh64/a.out.h | 38 include/asm-sh64/atomic.h | 158 - include/asm-sh64/auxvec.h | 4 include/asm-sh64/bitops.h | 155 - include/asm-sh64/bug.h | 19 include/asm-sh64/bugs.h | 38 include/asm-sh64/byteorder.h | 49 include/asm-sh64/cache.h | 139 - include/asm-sh64/cacheflush.h | 50 include/asm-sh64/cayman.h | 20 include/asm-sh64/checksum.h | 82 include/asm-sh64/cpumask.h | 6 include/asm-sh64/cputime.h | 6 include/asm-sh64/current.h | 28 include/asm-sh64/delay.h | 11 include/asm-sh64/device.h | 7 include/asm-sh64/div64.h | 6 include/asm-sh64/dma-mapping.h | 194 -- include/asm-sh64/dma.h | 41 include/asm-sh64/elf.h | 107 - include/asm-sh64/emergency-restart.h | 6 include/asm-sh64/errno.h | 6 include/asm-sh64/fb.h | 19 include/asm-sh64/fcntl.h | 1 include/asm-sh64/futex.h | 6 include/asm-sh64/gpio.h | 8 include/asm-sh64/hardirq.h | 18 include/asm-sh64/hardware.h | 22 include/asm-sh64/hw_irq.h | 15 include/asm-sh64/ide.h | 29 include/asm-sh64/io.h | 196 -- include/asm-sh64/ioctl.h | 1 include/asm-sh64/ioctls.h | 116 - include/asm-sh64/ipcbuf.h | 40 include/asm-sh64/irq.h | 144 - include/asm-sh64/irq_regs.h | 1 include/asm-sh64/kdebug.h | 1 include/asm-sh64/keyboard.h | 70 include/asm-sh64/kmap_types.h | 7 include/asm-sh64/linkage.h | 7 include/asm-sh64/local.h | 7 include/asm-sh64/mc146818rtc.h | 7 include/asm-sh64/mman.h | 6 include/asm-sh64/mmu.h | 7 include/asm-sh64/mmu_context.h | 208 -- include/asm-sh64/module.h | 20 include/asm-sh64/msgbuf.h | 42 include/asm-sh64/mutex.h | 9 include/asm-sh64/namei.h | 24 include/asm-sh64/page.h | 119 - include/asm-sh64/param.h | 42 include/asm-sh64/pci.h | 102 - include/asm-sh64/percpu.h | 6 include/asm-sh64/pgalloc.h | 125 - include/asm-sh64/pgtable.h | 496 ----- include/asm-sh64/platform.h | 64 include/asm-sh64/poll.h | 8 include/asm-sh64/posix_types.h | 131 - include/asm-sh64/processor.h | 287 --- include/asm-sh64/ptrace.h | 35 include/asm-sh64/registers.h | 106 - include/asm-sh64/resource.h | 6 include/asm-sh64/scatterlist.h | 37 include/asm-sh64/sci.h | 1 include/asm-sh64/sections.h | 7 include/asm-sh64/segment.h | 6 include/asm-sh64/semaphore-helper.h | 101 - include/asm-sh64/semaphore.h | 119 - include/asm-sh64/sembuf.h | 36 include/asm-sh64/serial.h | 31 include/asm-sh64/setup.h | 22 include/asm-sh64/shmbuf.h | 53 include/asm-sh64/shmparam.h | 12 include/asm-sh64/sigcontext.h | 30 include/asm-sh64/siginfo.h | 6 include/asm-sh64/signal.h | 159 - include/asm-sh64/smp.h | 15 include/asm-sh64/socket.h | 6 include/asm-sh64/sockios.h | 25 include/asm-sh64/spinlock.h | 17 include/asm-sh64/stat.h | 88 include/asm-sh64/statfs.h | 6 include/asm-sh64/string.h | 21 include/asm-sh64/system.h | 190 - include/asm-sh64/termbits.h | 6 include/asm-sh64/termios.h | 99 - include/asm-sh64/thread_info.h | 91 include/asm-sh64/timex.h | 31 include/asm-sh64/tlb.h | 92 include/asm-sh64/tlbflush.h | 27 include/asm-sh64/topology.h | 6 include/asm-sh64/types.h | 74 include/asm-sh64/uaccess.h | 316 --- include/asm-sh64/ucontext.h | 23 include/asm-sh64/unaligned.h | 17 include/asm-sh64/unistd.h | 417 ---- include/asm-sh64/user.h | 70 init/Kconfig | 2 mm/Kconfig | 2 403 files changed, 27725 insertions(+), 32967 deletions(-) diff -puN Makefile~git-sh Makefile --- a/Makefile~git-sh +++ a/Makefile @@ -169,7 +169,7 @@ SUBARCH := $(shell uname -m | sed -e s/i -e s/arm.*/arm/ -e s/sa110/arm/ \ -e s/s390x/s390/ -e s/parisc64/parisc/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ - -e s/sh[234].*/sh/ ) + -e s/sh.*/sh/ ) # Cross compiling and selecting different set of gcc/bin-utils # --------------------------------------------------------------------------- diff -puN arch/sh/Kconfig~git-sh arch/sh/Kconfig --- a/arch/sh/Kconfig~git-sh +++ a/arch/sh/Kconfig @@ -6,8 +6,7 @@ mainmenu "Linux/SuperH Kernel Configuration" config SUPERH - bool - default y + def_bool y select EMBEDDED help The SuperH is a RISC processor targeted for use in embedded systems @@ -15,36 +14,36 @@ config SUPERH gaming console. The SuperH port has a home page at . +config SUPERH32 + def_bool !SUPERH64 + +config SUPERH64 + def_bool y if CPU_SH5 + config RWSEM_GENERIC_SPINLOCK - bool - default y + def_bool y config RWSEM_XCHGADD_ALGORITHM bool config GENERIC_BUG def_bool y - depends on BUG + depends on BUG && SUPERH32 config GENERIC_FIND_NEXT_BIT - bool - default y + def_bool y config GENERIC_HWEIGHT - bool - default y + def_bool y config GENERIC_HARDIRQS - bool - default y + def_bool y config GENERIC_IRQ_PROBE - bool - default y + def_bool y config GENERIC_CALIBRATE_DELAY - bool - default y + def_bool y config GENERIC_IOMAP bool @@ -75,20 +74,16 @@ config ARCH_MAY_HAVE_PC_FDC bool config STACKTRACE_SUPPORT - bool - default y + def_bool y config LOCKDEP_SUPPORT - bool - default y + def_bool y config ARCH_HAS_ILOG2_U32 - bool - default n + def_bool n config ARCH_HAS_ILOG2_U64 - bool - default n + def_bool n config ARCH_NO_VIRT_TO_BUS def_bool y @@ -97,110 +92,221 @@ source "init/Kconfig" menu "System type" -source "arch/sh/mm/Kconfig" +# +# Processor families +# +config CPU_SH2 + bool + +config CPU_SH2A + bool + select CPU_SH2 + +config CPU_SH3 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + +config CPU_SH4 + bool + select CPU_HAS_INTEVT + select CPU_HAS_SR_RB + select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2 + select CPU_HAS_FPU if !CPU_SH4AL_DSP + +config CPU_SH4A + bool + select CPU_SH4 + +config CPU_SH4AL_DSP + bool + select CPU_SH4A + select CPU_HAS_DSP + +config CPU_SH5 + bool + select CPU_HAS_FPU -menu "Processor features" +config CPU_SHX2 + bool + +config CPU_SHX3 + bool choice - prompt "Endianess selection" - default CPU_LITTLE_ENDIAN + prompt "Processor sub-type selection" + +# +# Processor subtypes +# + +# SH-2 Processor Support + +config CPU_SUBTYPE_SH7619 + bool "Support SH7619 processor" + select CPU_SH2 + +# SH-2A Processor Support + +config CPU_SUBTYPE_SH7203 + bool "Support SH7203 processor" + select CPU_SH2A + select CPU_HAS_FPU + +config CPU_SUBTYPE_SH7206 + bool "Support SH7206 processor" + select CPU_SH2A + +config CPU_SUBTYPE_SH7263 + bool "Support SH7263 processor" + select CPU_SH2A + select CPU_HAS_FPU + +# SH-3 Processor Support + +config CPU_SUBTYPE_SH7705 + bool "Support SH7705 processor" + select CPU_SH3 + +config CPU_SUBTYPE_SH7706 + bool "Support SH7706 processor" + select CPU_SH3 help - Some SuperH machines can be configured for either little or big - endian byte order. These modes require different kernels. + Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU. -config CPU_LITTLE_ENDIAN - bool "Little Endian" +config CPU_SUBTYPE_SH7707 + bool "Support SH7707 processor" + select CPU_SH3 + help + Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. -config CPU_BIG_ENDIAN - bool "Big Endian" +config CPU_SUBTYPE_SH7708 + bool "Support SH7708 processor" + select CPU_SH3 + help + Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or + if you have a 100 Mhz SH-3 HD6417708R CPU. -endchoice +config CPU_SUBTYPE_SH7709 + bool "Support SH7709 processor" + select CPU_SH3 + help + Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. -config SH_FPU - bool "FPU support" - depends on CPU_HAS_FPU - default y - help - Selecting this option will enable support for SH processors that - have FPU units (ie, SH77xx). - - This option must be set in order to enable the FPU. - -config SH_FPU_EMU - bool "FPU emulation support" - depends on !SH_FPU && EXPERIMENTAL - default n - help - Selecting this option will enable support for software FPU emulation. - Most SH-3 users will want to say Y here, whereas most SH-4 users will - want to say N. - -config SH_DSP - bool "DSP support" - depends on CPU_HAS_DSP - default y - help - Selecting this option will enable support for SH processors that - have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP). - - This option must be set in order to enable the DSP. - -config SH_ADC - bool "ADC support" - depends on CPU_SH3 - default y +config CPU_SUBTYPE_SH7710 + bool "Support SH7710 processor" + select CPU_SH3 + select CPU_HAS_DSP help - Selecting this option will allow the Linux kernel to use SH3 on-chip - ADC module. + Select SH7710 if you have a SH3-DSP SH7710 CPU. - If unsure, say N. +config CPU_SUBTYPE_SH7712 + bool "Support SH7712 processor" + select CPU_SH3 + select CPU_HAS_DSP + help + Select SH7712 if you have a SH3-DSP SH7712 CPU. -config SH_STORE_QUEUES - bool "Support for Store Queues" - depends on CPU_SH4 - help - Selecting this option will enable an in-kernel API for manipulating - the store queues integrated in the SH-4 processors. - -config SPECULATIVE_EXECUTION - bool "Speculative subroutine return" - depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL - help - This enables support for a speculative instruction fetch for - subroutine return. There are various pitfalls associated with - this, as outlined in the SH7780 hardware manual. +config CPU_SUBTYPE_SH7720 + bool "Support SH7720 processor" + select CPU_SH3 + select CPU_HAS_DSP + help + Select SH7720 if you have a SH3-DSP SH7720 CPU. - If unsure, say N. +# SH-4 Processor Support -config CPU_HAS_INTEVT - bool +config CPU_SUBTYPE_SH7750 + bool "Support SH7750 processor" + select CPU_SH4 + help + Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. -config CPU_HAS_MASKREG_IRQ - bool +config CPU_SUBTYPE_SH7091 + bool "Support SH7091 processor" + select CPU_SH4 + help + Select SH7091 if you have an SH-4 based Sega device (such as + the Dreamcast, Naomi, and Naomi 2). -config CPU_HAS_IPR_IRQ - bool +config CPU_SUBTYPE_SH7750R + bool "Support SH7750R processor" + select CPU_SH4 -config CPU_HAS_SR_RB - bool +config CPU_SUBTYPE_SH7750S + bool "Support SH7750S processor" + select CPU_SH4 + +config CPU_SUBTYPE_SH7751 + bool "Support SH7751 processor" + select CPU_SH4 help - This will enable the use of SR.RB register bank usage. Processors - that are lacking this bit must have another method in place for - accomplishing what is taken care of by the banked registers. + Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, + or if you have a HD6417751R CPU. - See for further - information on SR.RB and register banking in the kernel in general. +config CPU_SUBTYPE_SH7751R + bool "Support SH7751R processor" + select CPU_SH4 -config CPU_HAS_PTEA - bool +config CPU_SUBTYPE_SH7760 + bool "Support SH7760 processor" + select CPU_SH4 -config CPU_HAS_DSP - bool +config CPU_SUBTYPE_SH4_202 + bool "Support SH4-202 processor" + select CPU_SH4 -config CPU_HAS_FPU - bool +# SH-4A Processor Support -endmenu +config CPU_SUBTYPE_SH7770 + bool "Support SH7770 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7780 + bool "Support SH7780 processor" + select CPU_SH4A + +config CPU_SUBTYPE_SH7785 + bool "Support SH7785 processor" + select CPU_SH4A + select CPU_SHX2 + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_NUMA + +config CPU_SUBTYPE_SHX3 + bool "Support SH-X3 processor" + select CPU_SH4A + select CPU_SHX3 + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_NUMA + select SYS_SUPPORTS_SMP + +# SH4AL-DSP Processor Support + +config CPU_SUBTYPE_SH7343 + bool "Support SH7343 processor" + select CPU_SH4AL_DSP + +config CPU_SUBTYPE_SH7722 + bool "Support SH7722 processor" + select CPU_SH4AL_DSP + select CPU_SHX2 + select ARCH_SPARSEMEM_ENABLE + select SYS_SUPPORTS_NUMA + +# SH-5 Processor Support + +config CPU_SUBTYPE_SH5_101 + bool "Support SH5-101 processor" + select CPU_SH5 + +config CPU_SUBTYPE_SH5_103 + bool "Support SH5-103 processor" + +endchoice + +source "arch/sh/mm/Kconfig" +source "arch/sh/Kconfig.cpu" menu "Board support" @@ -399,6 +505,11 @@ config SH_MAGIC_PANEL_R2 help Select Magic Panel R2 if configuring for Magic Panel R2. +config SH_CAYMAN + bool "Hitachi Cayman" + depends on CPU_SUBTYPE_SH5_101 || CPU_SUBTYPE_SH5_103 + select SYS_SUPPORTS_PCI + endmenu source "arch/sh/boards/renesas/hs7751rvoip/Kconfig" @@ -409,25 +520,25 @@ source "arch/sh/boards/magicpanelr2/Kcon menu "Timer and clock configuration" config SH_TMU - bool "TMU timer support" + def_bool y + prompt "TMU timer support" depends on CPU_SH3 || CPU_SH4 select GENERIC_TIME select GENERIC_CLOCKEVENTS - default y help This enables the use of the TMU as the system timer. config SH_CMT - bool "CMT timer support" + def_bool y + prompt "CMT timer support" depends on CPU_SH2 - default y help This enables the use of the CMT as the system timer. config SH_MTU2 - bool "MTU2 timer support" + def_bool n + prompt "MTU2 timer support" depends on CPU_SH2A - default n help This enables the use of the MTU2 as the system timer. @@ -445,7 +556,8 @@ config SH_PCLK_FREQ default "32000000" if CPU_SUBTYPE_SH7722 default "33333333" if CPU_SUBTYPE_SH7770 || \ CPU_SUBTYPE_SH7760 || CPU_SUBTYPE_SH7705 || \ - CPU_SUBTYPE_SH7206 + CPU_SUBTYPE_SH7203 || CPU_SUBTYPE_SH7206 || \ + CPU_SUBTYPE_SH7263 default "60000000" if CPU_SUBTYPE_SH7751 || CPU_SUBTYPE_SH7751R default "66000000" if CPU_SUBTYPE_SH4_202 default "50000000" @@ -456,7 +568,7 @@ config SH_PCLK_FREQ config SH_CLK_MD int "CPU Mode Pin Setting" - depends on CPU_SUBTYPE_SH7619 || CPU_SUBTYPE_SH7206 + depends on CPU_SH2 default 6 if CPU_SUBTYPE_SH7206 default 5 if CPU_SUBTYPE_SH7619 default 0 @@ -490,9 +602,8 @@ source "arch/sh/drivers/Kconfig" endmenu config ISA_DMA_API - bool + def_bool y depends on SH_MPC1211 - default y menu "Kernel features" @@ -570,7 +681,7 @@ source "kernel/Kconfig.preempt" config GUSA def_bool y - depends on !SMP + depends on !SMP && SUPERH32 help This enables support for gUSA (general UserSpace Atomicity). This is the default implementation for both UP and non-ll/sc @@ -582,6 +693,16 @@ config GUSA This should only be disabled for special cases where alternate atomicity implementations exist. +config GUSA_RB + bool "Implement atomic operations by roll-back (gRB) (EXPERIMENTAL)" + depends on GUSA && CPU_SH3 || (CPU_SH4 && !CPU_SH4A) + help + Enabling this option will allow the kernel to implement some + atomic operations using a software implemention of load-locked/ + store-conditional (LLSC). On machines which do not have hardware + LLSC, this should be more efficient than the other alternative of + disabling insterrupts around the atomic sequence. + endmenu menu "Boot options" diff -puN /dev/null arch/sh/Kconfig.cpu --- /dev/null +++ a/arch/sh/Kconfig.cpu @@ -0,0 +1,115 @@ +menu "Processor features" + +choice + prompt "Endianess selection" + default CPU_LITTLE_ENDIAN + help + Some SuperH machines can be configured for either little or big + endian byte order. These modes require different kernels. + +config CPU_LITTLE_ENDIAN + bool "Little Endian" + +config CPU_BIG_ENDIAN + bool "Big Endian" + +endchoice + +config SH_FPU + def_bool y + prompt "FPU support" + depends on CPU_HAS_FPU + help + Selecting this option will enable support for SH processors that + have FPU units (ie, SH77xx). + + This option must be set in order to enable the FPU. + +config SH64_FPU_DENORM_FLUSH + bool "Flush floating point denorms to zero" + depends on SH_FPU && SUPERH64 + +config SH_FPU_EMU + def_bool n + prompt "FPU emulation support" + depends on !SH_FPU && EXPERIMENTAL + help + Selecting this option will enable support for software FPU emulation. + Most SH-3 users will want to say Y here, whereas most SH-4 users will + want to say N. + +config SH_DSP + def_bool y + prompt "DSP support" + depends on CPU_HAS_DSP + help + Selecting this option will enable support for SH processors that + have DSP units (ie, SH2-DSP, SH3-DSP, and SH4AL-DSP). + + This option must be set in order to enable the DSP. + +config SH_ADC + def_bool y + prompt "ADC support" + depends on CPU_SH3 + help + Selecting this option will allow the Linux kernel to use SH3 on-chip + ADC module. + + If unsure, say N. + +config SH_STORE_QUEUES + bool "Support for Store Queues" + depends on CPU_SH4 + help + Selecting this option will enable an in-kernel API for manipulating + the store queues integrated in the SH-4 processors. + +config SPECULATIVE_EXECUTION + bool "Speculative subroutine return" + depends on CPU_SUBTYPE_SH7780 && EXPERIMENTAL + help + This enables support for a speculative instruction fetch for + subroutine return. There are various pitfalls associated with + this, as outlined in the SH7780 hardware manual. + + If unsure, say N. + +config SH64_USER_MISALIGNED_FIXUP + def_bool y + prompt "Fixup misaligned loads/stores occurring in user mode" + depends on SUPERH64 + +config SH64_ID2815_WORKAROUND + bool "Include workaround for SH5-101 cut2 silicon defect ID2815" + depends on CPU_SUBTYPE_SH5_101 + +config CPU_HAS_INTEVT + bool + +config CPU_HAS_MASKREG_IRQ + bool + +config CPU_HAS_IPR_IRQ + bool + +config CPU_HAS_SR_RB + bool + help + This will enable the use of SR.RB register bank usage. Processors + that are lacking this bit must have another method in place for + accomplishing what is taken care of by the banked registers. + + See for further + information on SR.RB and register banking in the kernel in general. + +config CPU_HAS_PTEA + bool + +config CPU_HAS_DSP + bool + +config CPU_HAS_FPU + bool + +endmenu diff -puN arch/sh/Kconfig.debug~git-sh arch/sh/Kconfig.debug --- a/arch/sh/Kconfig.debug~git-sh +++ a/arch/sh/Kconfig.debug @@ -1,8 +1,7 @@ menu "Kernel hacking" config TRACE_IRQFLAGS_SUPPORT - bool - default y + def_bool y source "lib/Kconfig.debug" @@ -32,7 +31,8 @@ config EARLY_SCIF_CONSOLE_PORT depends on EARLY_SCIF_CONSOLE default "0xffe00000" if CPU_SUBTYPE_SH7780 default "0xffea0000" if CPU_SUBTYPE_SH7785 - default "0xfffe9800" if CPU_SUBTYPE_SH7206 + default "0xfffe8000" if CPU_SUBTYPE_SH7203 + default "0xfffe9800" if CPU_SUBTYPE_SH7206 || CPU_SUBTYPE_SH7263 default "0xf8420000" if CPU_SUBTYPE_SH7619 default "0xa4400000" if CPU_SUBTYPE_SH7712 || CPU_SUBTYPE_SH7705 default "0xa4430000" if CPU_SUBTYPE_SH7720 @@ -62,7 +62,7 @@ config DEBUG_BOOTMEM config DEBUG_STACKOVERFLOW bool "Check for stack overflows" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && SUPERH32 help This option will cause messages to be printed if free stack space drops below a certain limit. @@ -88,7 +88,7 @@ config 4KSTACKS config IRQSTACKS bool "Use separate kernel stacks when processing interrupts" - depends on DEBUG_KERNEL + depends on DEBUG_KERNEL && SUPERH32 help If you say Y here the kernel will use separate kernel stacks for handling hard and soft interrupts. This can help avoid @@ -119,19 +119,19 @@ config COMPILE_OPTIONS depends on MORE_COMPILE_OPTIONS config KGDB_NMI - bool "Enter KGDB on NMI" - default n + def_bool n + prompt "Enter KGDB on NMI" config SH_KGDB_CONSOLE - bool "Console messages through GDB" + def_bool n + prompt "Console messages through GDB" depends on !SERIAL_SH_SCI_CONSOLE && SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE - default n config KGDB_SYSRQ - bool "Allow SysRq 'G' to enter KGDB" + def_bool y + prompt "Allow SysRq 'G' to enter KGDB" depends on MAGIC_SYSRQ - default y comment "Serial port setup" @@ -174,4 +174,29 @@ endchoice endmenu +if SUPERH64 + +config SH64_PROC_ASIDS + bool "Debug: report ASIDs through /proc/asids" + depends on PROC_FS + +config SH64_SR_WATCH + bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" + +config POOR_MANS_STRACE + bool "Debug: enable rudimentary strace facility" + help + This option allows system calls to be traced to the console. It also + aids in detecting kernel stack underflow. It is useful for debugging + early-userland problems (e.g. init incurring fatal exceptions.) + +config SH_ALPHANUMERIC + bool "Enable debug outputs to on-board alphanumeric display" + depends on SH_CAYMAN + +config SH_NO_BSS_INIT + bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)" + +endif + endmenu diff -puN arch/sh/Makefile~git-sh arch/sh/Makefile --- a/arch/sh/Makefile~git-sh +++ a/arch/sh/Makefile @@ -1,17 +1,13 @@ -# $Id: Makefile,v 1.35 2004/04/15 03:39:20 sugioka Exp $ # -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. +# arch/sh/Makefile # # Copyright (C) 1999 Kaz Kojima # Copyright (C) 2002, 2003, 2004 Paul Mundt # Copyright (C) 2002 M. R. Brown # -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. # isa-y := any isa-$(CONFIG_SH_DSP) := sh @@ -21,13 +17,9 @@ isa-$(CONFIG_CPU_SH3) := sh3 isa-$(CONFIG_CPU_SH4) := sh4 isa-$(CONFIG_CPU_SH4A) := sh4a isa-$(CONFIG_CPU_SH4AL_DSP) := sh4al - +isa-$(CONFIG_CPU_SH5) := shmedia isa-$(CONFIG_SH_DSP) := $(isa-y)-dsp -ifndef CONFIG_MMU -isa-y := $(isa-y)-nommu -endif - ifndef CONFIG_SH_DSP ifndef CONFIG_SH_FPU isa-y := $(isa-y)-nofpu @@ -44,6 +36,7 @@ cflags-$(CONFIG_CPU_SH4) := $(call cc-o $(call cc-option,-mno-implicit-fp,-m4-nofpu) cflags-$(CONFIG_CPU_SH4A) += $(call cc-option,-m4a,) \ $(call cc-option,-m4a-nofpu,) +cflags-$(CONFIG_CPU_SH5) := $(call cc-option,-m5-32media-nofpu,) cflags-$(CONFIG_CPU_BIG_ENDIAN) += -mb cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -ml @@ -66,22 +59,27 @@ cflags-y += $(isaflags-y) -ffreestanding cflags-$(CONFIG_MORE_COMPILE_OPTIONS) += \ $(shell echo $(CONFIG_COMPILE_OPTIONS) | sed -e 's/"//g') -OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment -R .stab -R .stabstr -S +OBJCOPYFLAGS := -O binary -R .note -R .note.gnu.build-id -R .comment \ + -R .stab -R .stabstr -S -# -# arch/sh/defconfig doesn't reflect any real hardware, and as such should -# never be used by anyone. Use a board-specific defconfig that has a -# reasonable chance of being current instead. -# -KBUILD_DEFCONFIG := r7780rp_defconfig +# Give the various platforms the opportunity to set default image types +defaultimage-$(CONFIG_SUPERH32) := zImage -KBUILD_IMAGE := arch/sh/boot/zImage +# Set some sensible Kbuild defaults +KBUILD_DEFCONFIG := r7780rp_defconfig +KBUILD_IMAGE := $(defaultimage-y) # # Choosing incompatible machines durings configuration will result in # error messages during linking. # -LDFLAGS_vmlinux += -e _stext +ifdef CONFIG_SUPERH32 +LDFLAGS_vmlinux += -e _stext +else +LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_PAGE_OFFSET) \ + --defsym phys_stext_shmedia=phys_stext+1 \ + -e phys_stext_shmedia +endif ifdef CONFIG_CPU_LITTLE_ENDIAN LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' @@ -94,7 +92,9 @@ endif KBUILD_CFLAGS += -pipe $(cflags-y) KBUILD_AFLAGS += $(cflags-y) -head-y := arch/sh/kernel/head.o arch/sh/kernel/init_task.o +head-y := arch/sh/kernel/init_task.o +head-$(CONFIG_SUPERH32) += arch/sh/kernel/head_32.o +head-$(CONFIG_SUPERH64) += arch/sh/kernel/head_64.o LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) @@ -127,6 +127,7 @@ machdir-$(CONFIG_SH_7206_SOLUTION_ENGINE machdir-$(CONFIG_SH_7619_SOLUTION_ENGINE) += se/7619 machdir-$(CONFIG_SH_LBOX_RE2) += lboxre2 machdir-$(CONFIG_SH_MAGIC_PANEL_R2) += magicpanelr2 +machdir-$(CONFIG_SH_CAYMAN) += cayman incdir-y := $(notdir $(machdir-y)) @@ -143,8 +144,11 @@ cpuincdir-$(CONFIG_CPU_SH2) := cpu-sh2 cpuincdir-$(CONFIG_CPU_SH2A) := cpu-sh2a cpuincdir-$(CONFIG_CPU_SH3) := cpu-sh3 cpuincdir-$(CONFIG_CPU_SH4) := cpu-sh4 +cpuincdir-$(CONFIG_CPU_SH5) := cpu-sh5 -libs-y := arch/sh/lib/ $(libs-y) $(LIBGCC) +libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) +libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) +libs-y += $(LIBGCC) drivers-y += arch/sh/drivers/ drivers-$(CONFIG_OPROFILE) += arch/sh/oprofile/ @@ -196,29 +200,61 @@ include/asm-sh/.mach: $(wildcard include done @touch $@ -archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools - PHONY += maketools FORCE + maketools: include/linux/version.h FORCE $(Q)$(MAKE) $(build)=arch/sh/tools include/asm-sh/machtypes.h -all: zImage +all: $(KBUILD_IMAGE) zImage uImage uImage.srec vmlinux.srec: vmlinux $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ compressed: zImage +archprepare: include/asm-sh/.cpu include/asm-sh/.mach maketools \ + arch/sh/lib64/syscalltab.h + archclean: $(Q)$(MAKE) $(clean)=$(boot) -CLEAN_FILES += include/asm-sh/machtypes.h \ - include/asm-sh/cpu include/asm-sh/.cpu \ - include/asm-sh/mach include/asm-sh/.mach - define archhelp @echo '* zImage - Compressed kernel image' @echo ' vmlinux.srec - Create an ELF S-record' @echo ' uImage - Create a bootable image for U-Boot' @echo ' uImage.srec - Create an S-record for U-Boot' endef + +define filechk_gen-syscalltab + (set -e; \ + echo "/*"; \ + echo " * DO NOT MODIFY."; \ + echo " *"; \ + echo " * This file was generated by arch/sh/Makefile"; \ + echo " * Any changes will be reverted at build time."; \ + echo " */"; \ + echo ""; \ + echo "#ifndef __SYSCALLTAB_H"; \ + echo "#define __SYSCALLTAB_H"; \ + echo ""; \ + echo "#include "; \ + echo ""; \ + echo "struct syscall_info {"; \ + echo " const char *name;"; \ + echo "} syscall_info_table[] = {"; \ + sed -e '/^.*\.long /!d;s// { "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \ + s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \ + echo "};"; \ + echo ""; \ + echo "#define NUM_SYSCALL_INFO_ENTRIES ARRAY_SIZE(syscall_info_table)";\ + echo ""; \ + echo "#endif /* __SYSCALLTAB_H */" ) +endef + +arch/sh/lib64/syscalltab.h: arch/sh/kernel/syscalls_64.S + $(call filechk,gen-syscalltab) + +CLEAN_FILES += arch/sh/lib64/syscalltab.h \ + include/asm-sh/machtypes.h \ + include/asm-sh/cpu include/asm-sh/.cpu \ + include/asm-sh/mach include/asm-sh/.mach diff -puN /dev/null arch/sh/boards/cayman/Makefile --- /dev/null +++ a/arch/sh/boards/cayman/Makefile @@ -0,0 +1,5 @@ +# +# Makefile for the Hitachi Cayman specific parts of the kernel +# +obj-y := setup.o irq.o +obj-$(CONFIG_HEARTBEAT) += led.o diff -puN /dev/null arch/sh/boards/cayman/irq.c --- /dev/null +++ a/arch/sh/boards/cayman/irq.c @@ -0,0 +1,197 @@ +/* + * arch/sh/mach-cayman/irq.c - SH-5 Cayman Interrupt Support + * + * This file handles the board specific parts of the Cayman interrupt system + * + * Copyright (C) 2002 Stuart Menefy + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +/* Setup for the SMSC FDC37C935 / LAN91C100FD */ +#define SMSC_IRQ IRQ_IRL1 + +/* Setup for PCI Bus 2, which transmits interrupts via the EPLD */ +#define PCI2_IRQ IRQ_IRL3 + +unsigned long epld_virt; + +#define EPLD_BASE 0x04002000 +#define EPLD_STATUS_BASE (epld_virt + 0x10) +#define EPLD_MASK_BASE (epld_virt + 0x20) + +/* Note the SMSC SuperIO chip and SMSC LAN chip interrupts are all muxed onto + the same SH-5 interrupt */ + +static irqreturn_t cayman_interrupt_smsc(int irq, void *dev_id) +{ + printk(KERN_INFO "CAYMAN: spurious SMSC interrupt\n"); + return IRQ_NONE; +} + +static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id) +{ + printk(KERN_INFO "CAYMAN: spurious PCI interrupt, IRQ %d\n", irq); + return IRQ_NONE; +} + +static struct irqaction cayman_action_smsc = { + .name = "Cayman SMSC Mux", + .handler = cayman_interrupt_smsc, + .flags = IRQF_DISABLED, +}; + +static struct irqaction cayman_action_pci2 = { + .name = "Cayman PCI2 Mux", + .handler = cayman_interrupt_pci2, + .flags = IRQF_DISABLED, +}; + +static void enable_cayman_irq(unsigned int irq) +{ + unsigned long flags; + unsigned long mask; + unsigned int reg; + unsigned char bit; + + irq -= START_EXT_IRQS; + reg = EPLD_MASK_BASE + ((irq / 8) << 2); + bit = 1<<(irq % 8); + local_irq_save(flags); + mask = ctrl_inl(reg); + mask |= bit; + ctrl_outl(mask, reg); + local_irq_restore(flags); +} + +void disable_cayman_irq(unsigned int irq) +{ + unsigned long flags; + unsigned long mask; + unsigned int reg; + unsigned char bit; + + irq -= START_EXT_IRQS; + reg = EPLD_MASK_BASE + ((irq / 8) << 2); + bit = 1<<(irq % 8); + local_irq_save(flags); + mask = ctrl_inl(reg); + mask &= ~bit; + ctrl_outl(mask, reg); + local_irq_restore(flags); +} + +static void ack_cayman_irq(unsigned int irq) +{ + disable_cayman_irq(irq); +} + +static void end_cayman_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_cayman_irq(irq); +} + +static unsigned int startup_cayman_irq(unsigned int irq) +{ + enable_cayman_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_cayman_irq(unsigned int irq) +{ + disable_cayman_irq(irq); +} + +struct hw_interrupt_type cayman_irq_type = { + .typename = "Cayman-IRQ", + .startup = startup_cayman_irq, + .shutdown = shutdown_cayman_irq, + .enable = enable_cayman_irq, + .disable = disable_cayman_irq, + .ack = ack_cayman_irq, + .end = end_cayman_irq, +}; + +int cayman_irq_demux(int evt) +{ + int irq = intc_evt_to_irq[evt]; + + if (irq == SMSC_IRQ) { + unsigned long status; + int i; + + status = ctrl_inl(EPLD_STATUS_BASE) & + ctrl_inl(EPLD_MASK_BASE) & 0xff; + if (status == 0) { + irq = -1; + } else { + for (i=0; i<8; i++) { + if (status & (1<= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) { + return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); + } + + return 0; +} +#endif + +void init_cayman_irq(void) +{ + int i; + + epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD"); + if (!epld_virt) { + printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n"); + return; + } + + for (i=0; i + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Flash the LEDs + */ +#include + +/* +** It is supposed these functions to be used for a low level +** debugging (via Cayman LEDs), hence to be available as soon +** as possible. +** Unfortunately Cayman LEDs relies on Cayman EPLD to be mapped +** (this happen when IRQ are initialized... quite late). +** These triky dependencies should be removed. Temporary, it +** may be enough to NOP until EPLD is mapped. +*/ + +extern unsigned long epld_virt; + +#define LED_ADDR (epld_virt + 0x008) +#define HDSP2534_ADDR (epld_virt + 0x100) + +void mach_led(int position, int value) +{ + if (!epld_virt) + return; + + if (value) + ctrl_outl(0, LED_ADDR); + else + ctrl_outl(1, LED_ADDR); + +} + +void mach_alphanum(int position, unsigned char value) +{ + if (!epld_virt) + return; + + ctrl_outb(value, HDSP2534_ADDR + 0xe0 + (position << 2)); +} + +void mach_alphanum_brightness(int setting) +{ + ctrl_outb(setting & 7, HDSP2534_ADDR + 0xc0); +} diff -puN /dev/null arch/sh/boards/cayman/setup.c --- /dev/null +++ a/arch/sh/boards/cayman/setup.c @@ -0,0 +1,187 @@ +/* + * arch/sh/mach-cayman/setup.c + * + * SH5 Cayman support + * + * Copyright (C) 2002 David J. Mckay & Benedict Gaster + * Copyright (C) 2003 - 2007 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +/* + * Platform Dependent Interrupt Priorities. + */ + +/* Using defaults defined in irq.h */ +#define RES NO_PRIORITY /* Disabled */ +#define IR0 IRL0_PRIORITY /* IRLs */ +#define IR1 IRL1_PRIORITY +#define IR2 IRL2_PRIORITY +#define IR3 IRL3_PRIORITY +#define PCA INTA_PRIORITY /* PCI Ints */ +#define PCB INTB_PRIORITY +#define PCC INTC_PRIORITY +#define PCD INTD_PRIORITY +#define SER TOP_PRIORITY +#define ERR TOP_PRIORITY +#define PW0 TOP_PRIORITY +#define PW1 TOP_PRIORITY +#define PW2 TOP_PRIORITY +#define PW3 TOP_PRIORITY +#define DM0 NO_PRIORITY /* DMA Ints */ +#define DM1 NO_PRIORITY +#define DM2 NO_PRIORITY +#define DM3 NO_PRIORITY +#define DAE NO_PRIORITY +#define TU0 TIMER_PRIORITY /* TMU Ints */ +#define TU1 NO_PRIORITY +#define TU2 NO_PRIORITY +#define TI2 NO_PRIORITY +#define ATI NO_PRIORITY /* RTC Ints */ +#define PRI NO_PRIORITY +#define CUI RTC_PRIORITY +#define ERI SCIF_PRIORITY /* SCIF Ints */ +#define RXI SCIF_PRIORITY +#define BRI SCIF_PRIORITY +#define TXI SCIF_PRIORITY +#define ITI TOP_PRIORITY /* WDT Ints */ + +/* Setup for the SMSC FDC37C935 */ +#define SMSC_SUPERIO_BASE 0x04000000 +#define SMSC_CONFIG_PORT_ADDR 0x3f0 +#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR +#define SMSC_DATA_PORT_ADDR 0x3f1 + +#define SMSC_ENTER_CONFIG_KEY 0x55 +#define SMSC_EXIT_CONFIG_KEY 0xaa + +#define SMCS_LOGICAL_DEV_INDEX 0x07 +#define SMSC_DEVICE_ID_INDEX 0x20 +#define SMSC_DEVICE_REV_INDEX 0x21 +#define SMSC_ACTIVATE_INDEX 0x30 +#define SMSC_PRIMARY_BASE_INDEX 0x60 +#define SMSC_SECONDARY_BASE_INDEX 0x62 +#define SMSC_PRIMARY_INT_INDEX 0x70 +#define SMSC_SECONDARY_INT_INDEX 0x72 + +#define SMSC_IDE1_DEVICE 1 +#define SMSC_KEYBOARD_DEVICE 7 +#define SMSC_CONFIG_REGISTERS 8 + +#define SMSC_SUPERIO_READ_INDEXED(index) ({ \ + outb((index), SMSC_INDEX_PORT_ADDR); \ + inb(SMSC_DATA_PORT_ADDR); }) +#define SMSC_SUPERIO_WRITE_INDEXED(val, index) ({ \ + outb((index), SMSC_INDEX_PORT_ADDR); \ + outb((val), SMSC_DATA_PORT_ADDR); }) + +#define IDE1_PRIMARY_BASE 0x01f0 +#define IDE1_SECONDARY_BASE 0x03f6 + +unsigned long smsc_superio_virt; + +int platform_int_priority[NR_INTC_IRQS] = { + IR0, IR1, IR2, IR3, PCA, PCB, PCC, PCD, /* IRQ 0- 7 */ + RES, RES, RES, RES, SER, ERR, PW3, PW2, /* IRQ 8-15 */ + PW1, PW0, DM0, DM1, DM2, DM3, DAE, RES, /* IRQ 16-23 */ + RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 24-31 */ + TU0, TU1, TU2, TI2, ATI, PRI, CUI, ERI, /* IRQ 32-39 */ + RXI, BRI, TXI, RES, RES, RES, RES, RES, /* IRQ 40-47 */ + RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 48-55 */ + RES, RES, RES, RES, RES, RES, RES, ITI, /* IRQ 56-63 */ +}; + +static int __init smsc_superio_setup(void) +{ + unsigned char devid, devrev; + + smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO"); + if (!smsc_superio_virt) { + panic("Unable to remap SMSC SuperIO\n"); + } + + /* Initially the chip is in run state */ + /* Put it into configuration state */ + outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); + outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); + + /* Read device ID info */ + devid = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_ID_INDEX); + devrev = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_REV_INDEX); + printk("SMSC SuperIO devid %02x rev %02x\n", devid, devrev); + + /* Select the keyboard device */ + SMSC_SUPERIO_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX); + + /* enable it */ + SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX); + + /* Select the interrupts */ + /* On a PC keyboard is IRQ1, mouse is IRQ12 */ + SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX); + SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX); + +#ifdef CONFIG_IDE + /* + * Only IDE1 exists on the Cayman + */ + + /* Power it on */ + SMSC_SUPERIO_WRITE_INDEXED(1 << SMSC_IDE1_DEVICE, 0x22); + + SMSC_SUPERIO_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX); + SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX); + + SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE >> 8, + SMSC_PRIMARY_BASE_INDEX + 0); + SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE & 0xff, + SMSC_PRIMARY_BASE_INDEX + 1); + + SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE >> 8, + SMSC_SECONDARY_BASE_INDEX + 0); + SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE & 0xff, + SMSC_SECONDARY_BASE_INDEX + 1); + + SMSC_SUPERIO_WRITE_INDEXED(14, SMSC_PRIMARY_INT_INDEX); + + SMSC_SUPERIO_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, + SMCS_LOGICAL_DEV_INDEX); + + SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */ + SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */ + SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */ + SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */ +#endif + + /* Exit the configuration state */ + outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); + + return 0; +} +__initcall(smsc_superio_setup); + +static void __iomem *cayman_ioport_map(unsigned long port, unsigned int len) +{ + if (port < 0x400) { + extern unsigned long smsc_superio_virt; + return (void __iomem *)((port << 2) | smsc_superio_virt); + } + + return (void __iomem *)port; +} + +extern void init_cayman_irq(void); + +static struct sh_machine_vector mv_cayman __initmv = { + .mv_name = "Hitachi Cayman", + .mv_nr_irqs = 64, + .mv_ioport_map = cayman_ioport_map, + .mv_init_irq = init_cayman_irq, +}; diff -puN arch/sh/boards/dreamcast/irq.c~git-sh arch/sh/boards/dreamcast/irq.c --- a/arch/sh/boards/dreamcast/irq.c~git-sh +++ a/arch/sh/boards/dreamcast/irq.c @@ -136,7 +136,7 @@ int systemasic_irq_demux(int irq) emr = EMR_BASE + (level << 4) + (level << 2); esr = ESR_BASE + (level << 2); - /* Mask the ESR to filter any spurious, unwanted interrtupts */ + /* Mask the ESR to filter any spurious, unwanted interrupts */ status = inl(esr); status &= inl(emr); diff -puN arch/sh/boot/Makefile~git-sh arch/sh/boot/Makefile --- a/arch/sh/boot/Makefile~git-sh +++ a/arch/sh/boot/Makefile @@ -35,17 +35,28 @@ $(obj)/compressed/vmlinux: FORCE KERNEL_LOAD := $(shell /bin/bash -c 'printf "0x%8x" \ $$[$(CONFIG_PAGE_OFFSET) + \ $(CONFIG_MEMORY_START) + \ + $(CONFIG_ZERO_PAGE_OFFSET)]') + +KERNEL_ENTRY := $(shell /bin/bash -c 'printf "0x%8x" \ + $$[$(CONFIG_PAGE_OFFSET) + \ + $(CONFIG_MEMORY_START) + \ $(CONFIG_ZERO_PAGE_OFFSET)+0x1000]') quiet_cmd_uimage = UIMAGE $@ cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sh -O linux -T kernel \ - -C none -a $(KERNEL_LOAD) -e $(KERNEL_LOAD) \ + -C none -a $(KERNEL_LOAD) -e $(KERNEL_ENTRY) \ -n 'Linux-$(KERNELRELEASE)' -d $< $@ -$(obj)/uImage: $(obj)/zImage FORCE +$(obj)/uImage: $(obj)/vmlinux.bin.gz FORCE $(call if_changed,uimage) @echo ' Image $@ is ready' +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) + OBJCOPYFLAGS_vmlinux.srec := -I binary -O srec $(obj)/vmlinux.srec: $(obj)/compressed/vmlinux $(call if_changed,objcopy) @@ -54,4 +65,5 @@ OBJCOPYFLAGS_uImage.srec := -I binary -O $(obj)/uImage.srec: $(obj)/uImage $(call if_changed,objcopy) -clean-files += uImage uImage.srec vmlinux.srec +clean-files += uImage uImage.srec vmlinux.srec \ + vmlinux.bin vmlinux.bin.gz diff -puN arch/sh/boot/compressed/Makefile~git-sh arch/sh/boot/compressed/Makefile --- a/arch/sh/boot/compressed/Makefile~git-sh +++ a/arch/sh/boot/compressed/Makefile @@ -1,43 +1,5 @@ -# -# linux/arch/sh/boot/compressed/Makefile -# -# create a compressed vmlinux image from the original vmlinux -# - -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o -EXTRA_AFLAGS := -traditional - -OBJECTS = $(obj)/head.o $(obj)/misc.o - -ifdef CONFIG_SH_STANDARD_BIOS -OBJECTS += $(obj)/../../kernel/sh_bios.o +ifeq ($(CONFIG_SUPERH32),y) +include ${srctree}/arch/sh/boot/compressed/Makefile_32 +else +include ${srctree}/arch/sh/boot/compressed/Makefile_64 endif - -# -# IMAGE_OFFSET is the load offset of the compression loader -# -IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ - $$[$(CONFIG_PAGE_OFFSET) + \ - $(CONFIG_MEMORY_START) + \ - $(CONFIG_BOOT_LINK_OFFSET)]') - -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) - -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds - - -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE - $(call if_changed,ld) - @: - -$(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE - $(call if_changed,gzip) - -LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh-linux -T -OBJCOPYFLAGS += -R .empty_zero_page - -$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,ld) diff -puN /dev/null arch/sh/boot/compressed/Makefile_32 --- /dev/null +++ a/arch/sh/boot/compressed/Makefile_32 @@ -0,0 +1,43 @@ +# +# linux/arch/sh/boot/compressed/Makefile +# +# create a compressed vmlinux image from the original vmlinux +# + +targets := vmlinux vmlinux.bin vmlinux.bin.gz \ + head_32.o misc_32.o piggy.o +EXTRA_AFLAGS := -traditional + +OBJECTS = $(obj)/head_32.o $(obj)/misc_32.o + +ifdef CONFIG_SH_STANDARD_BIOS +OBJECTS += $(obj)/../../kernel/sh_bios.o +endif + +# +# IMAGE_OFFSET is the load offset of the compression loader +# +IMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ + $$[$(CONFIG_PAGE_OFFSET) + \ + $(CONFIG_MEMORY_START) + \ + $(CONFIG_BOOT_LINK_OFFSET)]') + +LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) + +LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -e startup -T $(obj)/../../kernel/vmlinux.lds + +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE + $(call if_changed,ld) + @: + +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) + +LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh-linux -T +OBJCOPYFLAGS += -R .empty_zero_page + +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,ld) diff -puN /dev/null arch/sh/boot/compressed/Makefile_64 --- /dev/null +++ a/arch/sh/boot/compressed/Makefile_64 @@ -0,0 +1,45 @@ +# +# arch/sh/boot/compressed/Makefile_64 +# +# create a compressed vmlinux image from the original vmlinux +# +# Copyright (C) 2002 Stuart Menefy +# Copyright (C) 2004 Paul Mundt +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# + +targets := vmlinux vmlinux.bin vmlinux.bin.gz \ + head_64.o misc_64.o cache.o piggy.o +EXTRA_AFLAGS := -traditional + +OBJECTS := $(obj)/vmlinux_64.lds $(obj)/head_64.o $(obj)/misc_64.o \ + $(obj)/cache.o + +# +# ZIMAGE_OFFSET is the load offset of the compression loader +# (4M for the kernel plus 64K for this loader) +# +ZIMAGE_OFFSET := $(shell /bin/bash -c 'printf "0x%08x" \ + $$[$(CONFIG_PAGE_OFFSET)+0x400000+0x10000]') + +LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \ + -T $(obj)/../../kernel/vmlinux.lds + +$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE + $(call if_changed,ld) + @: + +$(obj)/vmlinux.bin: vmlinux FORCE + $(call if_changed,objcopy) + +$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE + $(call if_changed,gzip) + +LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T +OBJCOPYFLAGS += -R .empty_zero_page + +$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.gz FORCE + $(call if_changed,ld) diff -puN /dev/null arch/sh/boot/compressed/cache.c --- /dev/null +++ a/arch/sh/boot/compressed/cache.c @@ -0,0 +1,12 @@ +int cache_control(unsigned int command) +{ + volatile unsigned int *p = (volatile unsigned int *) 0x80000000; + int i; + + for (i = 0; i < (32 * 1024); i += 32) { + (void)*p; + p += (32 / sizeof (int)); + } + + return 0; +} diff -puN arch/sh/boot/compressed/head.S~git-sh /dev/null --- a/arch/sh/boot/compressed/head.S +++ /dev/null @@ -1,120 +0,0 @@ -/* - * linux/arch/sh/boot/compressed/head.S - * - * Copyright (C) 1999 Stuart Menefy - * Copyright (C) 2003 SUGIOKA Toshinobu - */ - -.text - -#include -#include - - .global startup -startup: - /* Load initial status register */ - mov.l init_sr, r1 - ldc r1, sr - - /* Move myself to proper location if necessary */ - mova 1f, r0 - mov.l 1f, r2 - cmp/eq r2, r0 - bt clear_bss - sub r0, r2 - mov.l bss_start_addr, r0 - mov #0xe0, r1 - and r1, r0 ! align cache line - mov.l text_start_addr, r3 - mov r0, r1 - sub r2, r1 -3: - mov.l @r1, r4 - mov.l @(4,r1), r5 - mov.l @(8,r1), r6 - mov.l @(12,r1), r7 - mov.l @(16,r1), r8 - mov.l @(20,r1), r9 - mov.l @(24,r1), r10 - mov.l @(28,r1), r11 - mov.l r4, @r0 - mov.l r5, @(4,r0) - mov.l r6, @(8,r0) - mov.l r7, @(12,r0) - mov.l r8, @(16,r0) - mov.l r9, @(20,r0) - mov.l r10, @(24,r0) - mov.l r11, @(28,r0) -#ifdef CONFIG_CPU_SH4 - ocbwb @r0 -#endif - cmp/hi r3, r0 - add #-32, r0 - bt/s 3b - add #-32, r1 - mov.l 2f, r0 - jmp @r0 - nop - - .align 2 -1: .long 1b -2: .long clear_bss -text_start_addr: - .long startup - - /* Clear BSS */ -clear_bss: - mov.l end_addr, r1 - mov.l bss_start_addr, r2 - mov #0, r0 -l1: - mov.l r0, @-r1 - cmp/eq r1,r2 - bf l1 - - /* Set the initial pointer. */ - mov.l init_stack_addr, r0 - mov.l @r0, r15 - - /* Decompress the kernel */ - mov.l decompress_kernel_addr, r0 - jsr @r0 - nop - - /* Jump to the start of the decompressed kernel */ - mov.l kernel_start_addr, r0 - jmp @r0 - nop - - .align 2 -bss_start_addr: - .long __bss_start -end_addr: - .long _end -init_sr: - .long 0x400000F0 /* Privileged mode, Bank=0, Block=0, IMASK=0xF */ -init_stack_addr: - .long stack_start -decompress_kernel_addr: - .long decompress_kernel -kernel_start_addr: - .long _text+PAGE_SIZE - - .align 9 -fake_headers_as_bzImage: - .word 0 - .ascii "HdrS" ! header signature - .word 0x0202 ! header version number (>= 0x0105) - ! or else old loadlin-1.5 will fail) - .word 0 ! default_switch - .word 0 ! SETUPSEG - .word 0x1000 - .word 0 ! pointing to kernel version string - .byte 0 ! = 0, old one (LILO, Loadlin, - ! 0xTV: T=0 for LILO - ! V = version - .byte 1 ! Load flags bzImage=1 - .word 0x8000 ! size to move, when setup is not - .long 0x100000 ! 0x100000 = default for big kernel - .long 0 ! address of loaded ramdisk image - .long 0 # its size in bytes diff -puN /dev/null arch/sh/boot/compressed/head_32.S --- /dev/null +++ a/arch/sh/boot/compressed/head_32.S @@ -0,0 +1,120 @@ +/* + * linux/arch/sh/boot/compressed/head.S + * + * Copyright (C) 1999 Stuart Menefy + * Copyright (C) 2003 SUGIOKA Toshinobu + */ + +.text + +#include +#include + + .global startup +startup: + /* Load initial status register */ + mov.l init_sr, r1 + ldc r1, sr + + /* Move myself to proper location if necessary */ + mova 1f, r0 + mov.l 1f, r2 + cmp/eq r2, r0 + bt clear_bss + sub r0, r2 + mov.l bss_start_addr, r0 + mov #0xe0, r1 + and r1, r0 ! align cache line + mov.l text_start_addr, r3 + mov r0, r1 + sub r2, r1 +3: + mov.l @r1, r4 + mov.l @(4,r1), r5 + mov.l @(8,r1), r6 + mov.l @(12,r1), r7 + mov.l @(16,r1), r8 + mov.l @(20,r1), r9 + mov.l @(24,r1), r10 + mov.l @(28,r1), r11 + mov.l r4, @r0 + mov.l r5, @(4,r0) + mov.l r6, @(8,r0) + mov.l r7, @(12,r0) + mov.l r8, @(16,r0) + mov.l r9, @(20,r0) + mov.l r10, @(24,r0) + mov.l r11, @(28,r0) +#ifdef CONFIG_CPU_SH4 + ocbwb @r0 +#endif + cmp/hi r3, r0 + add #-32, r0 + bt/s 3b + add #-32, r1 + mov.l 2f, r0 + jmp @r0 + nop + + .align 2 +1: .long 1b +2: .long clear_bss +text_start_addr: + .long startup + + /* Clear BSS */ +clear_bss: + mov.l end_addr, r1 + mov.l bss_start_addr, r2 + mov #0, r0 +l1: + mov.l r0, @-r1 + cmp/eq r1,r2 + bf l1 + + /* Set the initial pointer. */ + mov.l init_stack_addr, r0 + mov.l @r0, r15 + + /* Decompress the kernel */ + mov.l decompress_kernel_addr, r0 + jsr @r0 + nop + + /* Jump to the start of the decompressed kernel */ + mov.l kernel_start_addr, r0 + jmp @r0 + nop + + .align 2 +bss_start_addr: + .long __bss_start +end_addr: + .long _end +init_sr: + .long 0x400000F0 /* Privileged mode, Bank=0, Block=0, IMASK=0xF */ +init_stack_addr: + .long stack_start +decompress_kernel_addr: + .long decompress_kernel +kernel_start_addr: + .long _text+PAGE_SIZE + + .align 9 +fake_headers_as_bzImage: + .word 0 + .ascii "HdrS" ! header signature + .word 0x0202 ! header version number (>= 0x0105) + ! or else old loadlin-1.5 will fail) + .word 0 ! default_switch + .word 0 ! SETUPSEG + .word 0x1000 + .word 0 ! pointing to kernel version string + .byte 0 ! = 0, old one (LILO, Loadlin, + ! 0xTV: T=0 for LILO + ! V = version + .byte 1 ! Load flags bzImage=1 + .word 0x8000 ! size to move, when setup is not + .long 0x100000 ! 0x100000 = default for big kernel + .long 0 ! address of loaded ramdisk image + .long 0 # its size in bytes diff -puN /dev/null arch/sh/boot/compressed/head_64.S --- /dev/null +++ a/arch/sh/boot/compressed/head_64.S @@ -0,0 +1,163 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * arch/shmedia/boot/compressed/head.S + * + * Copied from + * arch/shmedia/kernel/head.S + * which carried the copyright: + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * Modification for compressed loader: + * Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com) + */ +#include +#include +#include +#include + +/* + * Fixed TLB entries to identity map the beginning of RAM + */ +#define MMUIR_TEXT_H 0x0000000000000003 | CONFIG_MEMORY_START + /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ +#define MMUIR_TEXT_L 0x000000000000009a | CONFIG_MEMORY_START + /* 512 Mb, Cacheable (Write-back), execute, Not User, Ph. Add. */ + +#define MMUDR_CACHED_H 0x0000000000000003 | CONFIG_MEMORY_START + /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ +#define MMUDR_CACHED_L 0x000000000000015a | CONFIG_MEMORY_START + /* 512 Mb, Cacheable (Write-back), read/write, Not User, Ph. Add. */ + +#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */ +#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */ + +#if 1 +#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* OCE + OCI + WB */ +#else +#define OCCR0_INIT_VAL OCCR0_OFF +#endif +#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */ + + .text + + .global startup +startup: + /* + * Prevent speculative fetch on device memory due to + * uninitialized target registers. + * This must be executed before the first branch. + */ + ptabs/u r63, tr0 + ptabs/u r63, tr1 + ptabs/u r63, tr2 + ptabs/u r63, tr3 + ptabs/u r63, tr4 + ptabs/u r63, tr5 + ptabs/u r63, tr6 + ptabs/u r63, tr7 + synci + + /* + * Set initial TLB entries for cached and uncached regions. + * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! + */ + /* Clear ITLBs */ + pta 1f, tr1 + movi ITLB_FIXED, r21 + movi ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22 +1: putcfg r21, 0, r63 /* Clear MMUIR[n].PTEH.V */ + addi r21, TLB_STEP, r21 + bne r21, r22, tr1 + + /* Clear DTLBs */ + pta 1f, tr1 + movi DTLB_FIXED, r21 + movi DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22 +1: putcfg r21, 0, r63 /* Clear MMUDR[n].PTEH.V */ + addi r21, TLB_STEP, r21 + bne r21, r22, tr1 + + /* Map one big (512Mb) page for ITLB */ + movi ITLB_FIXED, r21 + movi MMUIR_TEXT_L, r22 /* PTEL first */ + putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */ + movi MMUIR_TEXT_H, r22 /* PTEH last */ + putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */ + + /* Map one big CACHED (512Mb) page for DTLB */ + movi DTLB_FIXED, r21 + movi MMUDR_CACHED_L, r22 /* PTEL first */ + putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */ + movi MMUDR_CACHED_H, r22 /* PTEH last */ + putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ + + /* ICache */ + movi ICCR_BASE, r21 + movi ICCR0_INIT_VAL, r22 + movi ICCR1_INIT_VAL, r23 + putcfg r21, ICCR_REG0, r22 + putcfg r21, ICCR_REG1, r23 + synci + + /* OCache */ + movi OCCR_BASE, r21 + movi OCCR0_INIT_VAL, r22 + movi OCCR1_INIT_VAL, r23 + putcfg r21, OCCR_REG0, r22 + putcfg r21, OCCR_REG1, r23 + synco + + /* + * Enable the MMU. + * From here-on code can be non-PIC. + */ + movi SR_HARMLESS | SR_ENABLE_MMU, r22 + putcon r22, SSR + movi 1f, r22 + putcon r22, SPC + synco + rte /* And now go into the hyperspace ... */ +1: /* ... that's the next instruction ! */ + + /* Set initial stack pointer */ + movi datalabel stack_start, r0 + ld.l r0, 0, r15 + + /* + * Clear bss + */ + pt 1f, tr1 + movi datalabel __bss_start, r22 + movi datalabel _end, r23 +1: st.l r22, 0, r63 + addi r22, 4, r22 + bne r22, r23, tr1 + + /* + * Decompress the kernel. + */ + pt decompress_kernel, tr0 + blink tr0, r18 + + /* + * Disable the MMU. + */ + movi SR_HARMLESS, r22 + putcon r22, SSR + movi 1f, r22 + putcon r22, SPC + synco + rte /* And now go into the hyperspace ... */ +1: /* ... that's the next instruction ! */ + + /* Jump into the decompressed kernel */ + movi datalabel (CONFIG_MEMORY_START + 0x2000)+1, r19 + ptabs r19, tr0 + blink tr0, r18 + + /* Shouldn't return here, but just in case, loop forever */ + pt 1f, tr0 +1: blink tr0, r63 diff -puN arch/sh/boot/compressed/misc.c~git-sh /dev/null --- a/arch/sh/boot/compressed/misc.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * arch/sh/boot/compressed/misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * - * Adapted for SH by Stuart Menefy, Aug 1999 - * - * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000 - */ - -#include -#include -#include -#ifdef CONFIG_SH_STANDARD_BIOS -#include -#endif - -/* - * gzip declarations - */ - -#define OF(args) args -#define STATIC static - -#undef memset -#undef memcpy -#define memzero(s, n) memset ((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static int fill_inbuf(void); -static void flush_window(void); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -extern char input_data[]; -extern int input_len; - -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; - -static void *malloc(int size); -static void free(void *where); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -int puts(const char *); - -extern int _text; /* Defined in vmlinux.lds.S */ -extern int _end; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -#define HEAP_SIZE 0x10000 - -#include "../../../../lib/inflate.c" - -static void *malloc(int size) -{ - void *p; - - if (size <0) error("Malloc error"); - if (free_mem_ptr == 0) error("Memory error"); - - free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ - - p = (void *)free_mem_ptr; - free_mem_ptr += size; - - if (free_mem_ptr >= free_mem_end_ptr) - error("Out of memory"); - - return p; -} - -static void free(void *where) -{ /* Don't care */ -} - -static void gzip_mark(void **ptr) -{ - *ptr = (void *) free_mem_ptr; -} - -static void gzip_release(void **ptr) -{ - free_mem_ptr = (long) *ptr; -} - -#ifdef CONFIG_SH_STANDARD_BIOS -size_t strlen(const char *s) -{ - int i = 0; - - while (*s++) - i++; - return i; -} - -int puts(const char *s) -{ - int len = strlen(s); - sh_bios_console_write(s, len); - return len; -} -#else -int puts(const char *s) -{ - /* This should be updated to use the sh-sci routines */ - return 0; -} -#endif - -void* memset(void* s, int c, size_t n) -{ - int i; - char *ss = (char*)s; - - for (i=0;i> 8); - } - crc = c; - bytes_out += (ulg)outcnt; - output_ptr += (ulg)outcnt; - outcnt = 0; -} - -static void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while(1); /* Halt */ -} - -#define STACK_SIZE (4096) -long user_stack [STACK_SIZE]; -long* stack_start = &user_stack[STACK_SIZE]; - -void decompress_kernel(void) -{ - output_data = 0; - output_ptr = P2SEGADDR((unsigned long)&_text+PAGE_SIZE); - free_mem_ptr = (unsigned long)&_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - - makecrc(); - puts("Uncompressing Linux... "); - gunzip(); - puts("Ok, booting the kernel.\n"); -} diff -puN /dev/null arch/sh/boot/compressed/misc_32.c --- /dev/null +++ a/arch/sh/boot/compressed/misc_32.c @@ -0,0 +1,244 @@ +/* + * arch/sh/boot/compressed/misc.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * + * Adapted for SH by Stuart Menefy, Aug 1999 + * + * Modified to use standard LinuxSH BIOS by Greg Banks 7Jul2000 + */ + +#include +#include +#include +#ifdef CONFIG_SH_STANDARD_BIOS +#include +#endif + +/* + * gzip declarations + */ + +#define OF(args) args +#define STATIC static + +#undef memset +#undef memcpy +#define memzero(s, n) memset ((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +extern char input_data[]; +extern int input_len; + +static long bytes_out = 0; +static uch *output_data; +static unsigned long output_ptr = 0; + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +int puts(const char *); + +extern int _text; /* Defined in vmlinux.lds.S */ +extern int _end; +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#define HEAP_SIZE 0x10000 + +#include "../../../../lib/inflate.c" + +static void *malloc(int size) +{ + void *p; + + if (size <0) error("Malloc error"); + if (free_mem_ptr == 0) error("Memory error"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *)free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_end_ptr) + error("Out of memory"); + + return p; +} + +static void free(void *where) +{ /* Don't care */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} + +#ifdef CONFIG_SH_STANDARD_BIOS +size_t strlen(const char *s) +{ + int i = 0; + + while (*s++) + i++; + return i; +} + +int puts(const char *s) +{ + int len = strlen(s); + sh_bios_console_write(s, len); + return len; +} +#else +int puts(const char *s) +{ + /* This should be updated to use the sh-sci routines */ + return 0; +} +#endif + +void* memset(void* s, int c, size_t n) +{ + int i; + char *ss = (char*)s; + + for (i=0;i> 8); + } + crc = c; + bytes_out += (ulg)outcnt; + output_ptr += (ulg)outcnt; + outcnt = 0; +} + +static void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while(1); /* Halt */ +} + +#define STACK_SIZE (4096) +long user_stack [STACK_SIZE]; +long* stack_start = &user_stack[STACK_SIZE]; + +void decompress_kernel(void) +{ + output_data = 0; + output_ptr = PHYSADDR((unsigned long)&_text+PAGE_SIZE); +#ifdef CONFIG_29BIT + output_ptr |= P2SEG; +#endif + free_mem_ptr = (unsigned long)&_end; + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + + makecrc(); + puts("Uncompressing Linux... "); + gunzip(); + puts("Ok, booting the kernel.\n"); +} diff -puN /dev/null arch/sh/boot/compressed/misc_64.c --- /dev/null +++ a/arch/sh/boot/compressed/misc_64.c @@ -0,0 +1,250 @@ +/* + * arch/sh/boot/compressed/misc_64.c + * + * This is a collection of several routines from gzip-1.0.3 + * adapted for Linux. + * + * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 + * + * Adapted for SHmedia from sh by Stuart Menefy, May 2002 + */ + +#include + +/* cache.c */ +#define CACHE_ENABLE 0 +#define CACHE_DISABLE 1 +int cache_control(unsigned int command); + +/* + * gzip declarations + */ + +#define OF(args) args +#define STATIC static + +#undef memset +#undef memcpy +#define memzero(s, n) memset ((s), 0, (n)) + +typedef unsigned char uch; +typedef unsigned short ush; +typedef unsigned long ulg; + +#define WSIZE 0x8000 /* Window size must be at least 32k, */ + /* and a power of two */ + +static uch *inbuf; /* input buffer */ +static uch window[WSIZE]; /* Sliding window buffer */ + +static unsigned insize = 0; /* valid bytes in inbuf */ +static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ +static unsigned outcnt = 0; /* bytes in output buffer */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ +#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +#define RESERVED 0xC0 /* bit 6,7: reserved */ + +#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) + +/* Diagnostic functions */ +#ifdef DEBUG +# define Assert(cond,msg) {if(!(cond)) error(msg);} +# define Trace(x) fprintf x +# define Tracev(x) {if (verbose) fprintf x ;} +# define Tracevv(x) {if (verbose>1) fprintf x ;} +# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} +# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +static int fill_inbuf(void); +static void flush_window(void); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +extern char input_data[]; +extern int input_len; + +static long bytes_out = 0; +static uch *output_data; +static unsigned long output_ptr = 0; + +static void *malloc(int size); +static void free(void *where); +static void error(char *m); +static void gzip_mark(void **); +static void gzip_release(void **); + +static void puts(const char *); + +extern int _text; /* Defined in vmlinux.lds.S */ +extern int _end; +static unsigned long free_mem_ptr; +static unsigned long free_mem_end_ptr; + +#define HEAP_SIZE 0x10000 + +#include "../../../../lib/inflate.c" + +static void *malloc(int size) +{ + void *p; + + if (size < 0) + error("Malloc error\n"); + if (free_mem_ptr == 0) + error("Memory error\n"); + + free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ + + p = (void *) free_mem_ptr; + free_mem_ptr += size; + + if (free_mem_ptr >= free_mem_end_ptr) + error("\nOut of memory\n"); + + return p; +} + +static void free(void *where) +{ /* Don't care */ +} + +static void gzip_mark(void **ptr) +{ + *ptr = (void *) free_mem_ptr; +} + +static void gzip_release(void **ptr) +{ + free_mem_ptr = (long) *ptr; +} + +void puts(const char *s) +{ +} + +void *memset(void *s, int c, size_t n) +{ + int i; + char *ss = (char *) s; + + for (i = 0; i < n; i++) + ss[i] = c; + return s; +} + +void *memcpy(void *__dest, __const void *__src, size_t __n) +{ + int i; + char *d = (char *) __dest, *s = (char *) __src; + + for (i = 0; i < __n; i++) + d[i] = s[i]; + return __dest; +} + +/* =========================================================================== + * Fill the input buffer. This is called only when the buffer is empty + * and at least one byte is really needed. + */ +static int fill_inbuf(void) +{ + if (insize != 0) { + error("ran out of input data\n"); + } + + inbuf = input_data; + insize = input_len; + inptr = 1; + return inbuf[0]; +} + +/* =========================================================================== + * Write the output window window[0..outcnt-1] and update crc and bytes_out. + * (Used for the decompressed data only.) + */ +static void flush_window(void) +{ + ulg c = crc; /* temporary variable */ + unsigned n; + uch *in, *out, ch; + + in = window; + out = &output_data[output_ptr]; + for (n = 0; n < outcnt; n++) { + ch = *out++ = *in++; + c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8); + } + crc = c; + bytes_out += (ulg) outcnt; + output_ptr += (ulg) outcnt; + outcnt = 0; + puts("."); +} + +static void error(char *x) +{ + puts("\n\n"); + puts(x); + puts("\n\n -- System halted"); + + while (1) ; /* Halt */ +} + +#define STACK_SIZE (4096) +long __attribute__ ((aligned(8))) user_stack[STACK_SIZE]; +long *stack_start = &user_stack[STACK_SIZE]; + +void decompress_kernel(void) +{ + output_data = (uch *) (CONFIG_MEMORY_START + 0x2000); + free_mem_ptr = (unsigned long) &_end; + free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; + + makecrc(); + puts("Uncompressing Linux... "); + cache_control(CACHE_ENABLE); + gunzip(); + puts("\n"); + +#if 0 + /* When booting from ROM may want to do something like this if the + * boot loader doesn't. + */ + + /* Set up the parameters and command line */ + { + volatile unsigned int *parambase = + (int *) (CONFIG_MEMORY_START + 0x1000); + + parambase[0] = 0x1; /* MOUNT_ROOT_RDONLY */ + parambase[1] = 0x0; /* RAMDISK_FLAGS */ + parambase[2] = 0x0200; /* ORIG_ROOT_DEV */ + parambase[3] = 0x0; /* LOADER_TYPE */ + parambase[4] = 0x0; /* INITRD_START */ + parambase[5] = 0x0; /* INITRD_SIZE */ + parambase[6] = 0; + + strcpy((char *) ((int) parambase + 0x100), + "console=ttySC0,38400"); + } +#endif + + puts("Ok, booting the kernel.\n"); + + cache_control(CACHE_DISABLE); +} diff -puN /dev/null arch/sh/boot/compressed/vmlinux_64.lds --- /dev/null +++ a/arch/sh/boot/compressed/vmlinux_64.lds @@ -0,0 +1,64 @@ +/* + * ld script to make compressed SuperH/shmedia Linux kernel+decompression + * bootstrap + * Modified by Stuart Menefy from arch/sh/vmlinux.lds.S written by Niibe Yutaka + */ + + +#ifdef CONFIG_LITTLE_ENDIAN +/* OUTPUT_FORMAT("elf32-sh64l-linux", "elf32-sh64l-linux", "elf32-sh64l-linux") */ +#define NOP 0x6ff0fff0 +#else +/* OUTPUT_FORMAT("elf32-sh64", "elf32-sh64", "elf32-sh64") */ +#define NOP 0xf0fff06f +#endif + +OUTPUT_FORMAT("elf32-sh64-linux") +OUTPUT_ARCH(sh) +ENTRY(_start) + +#define ALIGNED_GAP(section, align) (((ADDR(section)+SIZEOF(section)+(align)-1) & ~((align)-1))-ADDR(section)) +#define FOLLOWING(section, align) AT (LOADADDR(section) + ALIGNED_GAP(section,align)) + +SECTIONS +{ + _text = .; /* Text and read-only data */ + + .text : { + *(.text) + *(.text64) + *(.text..SHmedia32) + *(.fixup) + *(.gnu.warning) + } = NOP + . = ALIGN(4); + .rodata : { *(.rodata) } + + /* There is no 'real' reason for eight byte alignment, four would work + * as well, but gdb downloads much (*4) faster with this. + */ + . = ALIGN(8); + .image : { *(.image) } + . = ALIGN(4); + _etext = .; /* End of text section */ + + .data : /* Data */ + FOLLOWING(.image, 4) + { + _data = .; + *(.data) + } + _data_image = LOADADDR(.data);/* Address of data section in ROM */ + + _edata = .; /* End of data section */ + + .stack : { stack = .; _stack = .; } + + . = ALIGN(4); + __bss_start = .; /* BSS */ + .bss : { + *(.bss) + } + . = ALIGN(4); + _end = . ; +} diff -puN /dev/null arch/sh/configs/cayman_defconfig --- /dev/null +++ a/arch/sh/configs/cayman_defconfig @@ -0,0 +1,1166 @@ +# +# Automatically generated make config: don't edit +# Linux kernel version: 2.6.24-rc3 +# Fri Nov 23 14:15:55 2007 +# +CONFIG_SUPERH=y +# CONFIG_SUPERH32 is not set +CONFIG_SUPERH64=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_HWEIGHT=y +CONFIG_GENERIC_HARDIRQS=y +CONFIG_GENERIC_IRQ_PROBE=y +CONFIG_GENERIC_CALIBRATE_DELAY=y +# CONFIG_GENERIC_TIME is not set +# CONFIG_GENERIC_CLOCKEVENTS is not set +CONFIG_SYS_SUPPORTS_PCI=y +CONFIG_STACKTRACE_SUPPORT=y +CONFIG_LOCKDEP_SUPPORT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_NO_VIRT_TO_BUS=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" + +# +# General setup +# +CONFIG_EXPERIMENTAL=y +CONFIG_BROKEN_ON_SMP=y +CONFIG_LOCK_KERNEL=y +CONFIG_INIT_ENV_ARG_LIMIT=32 +CONFIG_LOCALVERSION="" +CONFIG_LOCALVERSION_AUTO=y +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +CONFIG_POSIX_MQUEUE=y +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_AUDIT is not set +# CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_FAIR_USER_SCHED=y +# CONFIG_FAIR_CGROUP_SCHED is not set +CONFIG_SYSFS_DEPRECATED=y +# CONFIG_RELAY is not set +# CONFIG_BLK_DEV_INITRD is not set +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +CONFIG_SYSCTL=y +CONFIG_EMBEDDED=y +CONFIG_UID16=y +CONFIG_SYSCTL_SYSCALL=y +CONFIG_KALLSYMS=y +# CONFIG_KALLSYMS_ALL is not set +# CONFIG_KALLSYMS_EXTRA_PASS is not set +CONFIG_HOTPLUG=y +CONFIG_PRINTK=y +CONFIG_BUG=y +CONFIG_ELF_CORE=y +CONFIG_BASE_FULL=y +CONFIG_FUTEX=y +CONFIG_ANON_INODES=y +CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_EVENTFD=y +CONFIG_SHMEM=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLAB=y +# CONFIG_SLUB is not set +# CONFIG_SLOB is not set +CONFIG_RT_MUTEXES=y +# CONFIG_TINY_SHMEM is not set +CONFIG_BASE_SMALL=0 +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +# CONFIG_MODVERSIONS is not set +# CONFIG_MODULE_SRCVERSION_ALL is not set +CONFIG_KMOD=y +CONFIG_BLOCK=y +# CONFIG_LBD is not set +# CONFIG_BLK_DEV_IO_TRACE is not set +# CONFIG_LSF is not set +# CONFIG_BLK_DEV_BSG is not set + +# +# IO Schedulers +# +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_CFQ=y +# CONFIG_DEFAULT_AS is not set +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_CFQ=y +# CONFIG_DEFAULT_NOOP is not set +CONFIG_DEFAULT_IOSCHED="cfq" + +# +# System type +# +CONFIG_CPU_SH5=y +# CONFIG_CPU_SUBTYPE_SH7619 is not set +# CONFIG_CPU_SUBTYPE_SH7206 is not set +# CONFIG_CPU_SUBTYPE_SH7705 is not set +# CONFIG_CPU_SUBTYPE_SH7706 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +# CONFIG_CPU_SUBTYPE_SH7709 is not set +# CONFIG_CPU_SUBTYPE_SH7710 is not set +# CONFIG_CPU_SUBTYPE_SH7712 is not set +# CONFIG_CPU_SUBTYPE_SH7720 is not set +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7091 is not set +# CONFIG_CPU_SUBTYPE_SH7750R is not set +# CONFIG_CPU_SUBTYPE_SH7750S is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7751R is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_SH4_202 is not set +# CONFIG_CPU_SUBTYPE_SH7770 is not set +# CONFIG_CPU_SUBTYPE_SH7780 is not set +# CONFIG_CPU_SUBTYPE_SH7785 is not set +# CONFIG_CPU_SUBTYPE_SHX3 is not set +# CONFIG_CPU_SUBTYPE_SH7343 is not set +# CONFIG_CPU_SUBTYPE_SH7722 is not set +CONFIG_CPU_SUBTYPE_SH5_101=y +# CONFIG_CPU_SUBTYPE_SH5_103 is not set + +# +# Memory management options +# +CONFIG_QUICKLIST=y +CONFIG_MMU=y +CONFIG_PAGE_OFFSET=0x20000000 +CONFIG_MEMORY_START=0x80000000 +CONFIG_MEMORY_SIZE=0x00400000 +CONFIG_32BIT=y +CONFIG_ARCH_FLATMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_MAX_ACTIVE_REGIONS=1 +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PAGE_SIZE_64KB is not set +CONFIG_HUGETLB_PAGE_SIZE_64K=y +# CONFIG_HUGETLB_PAGE_SIZE_256K is not set +# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_4MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set +CONFIG_SELECT_MEMORY_MODEL=y +CONFIG_FLATMEM_MANUAL=y +# CONFIG_DISCONTIGMEM_MANUAL is not set +# CONFIG_SPARSEMEM_MANUAL is not set +CONFIG_FLATMEM=y +CONFIG_FLAT_NODE_MEM_MAP=y +CONFIG_SPARSEMEM_STATIC=y +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=2 + +# +# Cache configuration +# +# CONFIG_SH_DIRECT_MAPPED is not set +# CONFIG_CACHE_WRITEBACK is not set +# CONFIG_CACHE_WRITETHROUGH is not set +CONFIG_CACHE_OFF=y + +# +# Processor features +# +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_SH_FPU=y +# CONFIG_SH64_FPU_DENORM_FLUSH is not set +CONFIG_SH64_USER_MISALIGNED_FIXUP=y +CONFIG_SH64_ID2815_WORKAROUND=y +CONFIG_CPU_HAS_FPU=y + +# +# Board support +# +CONFIG_SH_CAYMAN=y + +# +# Timer and clock configuration +# +CONFIG_SH_TIMER_IRQ=16 +CONFIG_SH_PCLK_FREQ=50000000 +# CONFIG_TICK_ONESHOT is not set + +# +# CPU Frequency scaling +# +# CONFIG_CPU_FREQ is not set + +# +# DMA support +# + +# +# Companion Chips +# + +# +# Additional SuperH Device Drivers +# +CONFIG_HEARTBEAT=y +# CONFIG_PUSH_SWITCH is not set + +# +# Kernel features +# +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set +# CONFIG_HZ_1000 is not set +CONFIG_HZ=250 +# CONFIG_KEXEC is not set +# CONFIG_CRASH_DUMP is not set +# CONFIG_PREEMPT_NONE is not set +# CONFIG_PREEMPT_VOLUNTARY is not set +CONFIG_PREEMPT=y +CONFIG_PREEMPT_BKL=y +CONFIG_GUSA=y + +# +# Boot options +# +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +# CONFIG_CMDLINE_BOOL is not set + +# +# Bus options +# +CONFIG_PCI=y +CONFIG_SH_PCIDMA_NONCOHERENT=y +CONFIG_PCI_AUTO=y +CONFIG_PCI_AUTO_UPDATE_RESOURCES=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y +# CONFIG_PCI_DEBUG is not set +# CONFIG_PCCARD is not set +# CONFIG_HOTPLUG_PCI is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set + +# +# Networking +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set +# CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set +# CONFIG_NET_KEY is not set +CONFIG_INET=y +# CONFIG_IP_MULTICAST is not set +# CONFIG_IP_ADVANCED_ROUTER is not set +CONFIG_IP_FIB_HASH=y +CONFIG_IP_PNP=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_XFRM_TUNNEL is not set +# CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y +CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set +CONFIG_INET_DIAG=y +CONFIG_INET_TCP_DIAG=y +# CONFIG_TCP_CONG_ADVANCED is not set +CONFIG_TCP_CONG_CUBIC=y +CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set +# CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set +# CONFIG_NETFILTER is not set +# CONFIG_IP_DCCP is not set +# CONFIG_IP_SCTP is not set +# CONFIG_TIPC is not set +# CONFIG_ATM is not set +# CONFIG_BRIDGE is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_DECNET is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_IRDA is not set +# CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set +# CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +# CONFIG_FW_LOADER is not set +# CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set +# CONFIG_SYS_HYPERVISOR is not set +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# 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=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_SX8 is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_COUNT=16 +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_CDROM_PKTCDVD is not set +# CONFIG_ATA_OVER_ETH is not set +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set +# CONFIG_IDE is not set + +# +# SCSI device support +# +# CONFIG_RAID_ATTRS is not set +CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set +# CONFIG_SCSI_NETLINK is not set +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +# CONFIG_CHR_DEV_ST is not set +# CONFIG_CHR_DEV_OSST is not set +# CONFIG_BLK_DEV_SR is not set +# CONFIG_CHR_DEV_SG is not set +# CONFIG_CHR_DEV_SCH is not set + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +# CONFIG_SCSI_CONSTANTS is not set +# CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m + +# +# SCSI Transports +# +CONFIG_SCSI_SPI_ATTRS=y +# CONFIG_SCSI_FC_ATTRS is not set +# CONFIG_SCSI_ISCSI_ATTRS is not set +# CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set +CONFIG_SCSI_LOWLEVEL=y +# CONFIG_ISCSI_TCP is not set +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_9XXX is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_AIC94XX is not set +# CONFIG_SCSI_ARCMSR is not set +# CONFIG_MEGARAID_NEWGEN is not set +# CONFIG_MEGARAID_LEGACY is not set +# CONFIG_MEGARAID_SAS is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INITIO is not set +# CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_STEX is not set +# CONFIG_SCSI_SYM53C8XX_2 is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_ATA is not set +# CONFIG_MD is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_IEEE1394 is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set +# CONFIG_DUMMY is not set +# CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set +# CONFIG_EQUALIZER is not set +# CONFIG_TUN is not set +# CONFIG_VETH is not set +# CONFIG_IP1000 is not set +# CONFIG_ARCNET is not set +# CONFIG_PHYLIB is not set +CONFIG_NET_ETHERNET=y +# CONFIG_MII is not set +# CONFIG_AX88796 is not set +# CONFIG_STNIC is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +# CONFIG_CASSINI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_SMC91X is not set +# CONFIG_SMC911X is not set +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_NET_PCI is not set +# CONFIG_B44 is not set +CONFIG_NETDEV_1000=y +# CONFIG_ACENIC is not set +# CONFIG_DL2K is not set +# CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SKGE is not set +# CONFIG_SKY2 is not set +# CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2 is not set +# CONFIG_QLA3XXX is not set +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y +# CONFIG_CHELSIO_T1 is not set +# CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set +# CONFIG_IXGB is not set +# CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set +# CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set +# CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set +# CONFIG_TR is not set + +# +# Wireless LAN +# +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set +# 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_NET_FC is not set +# CONFIG_SHAPER is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +# CONFIG_ISDN is not set +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y +# CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +# CONFIG_INPUT_MOUSEDEV_PSAUX is not set +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Hardware I/O ports +# +# CONFIG_SERIO is not set +# CONFIG_GAMEPORT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set +# CONFIG_SERIAL_JSM is not set +CONFIG_UNIX98_PTYS=y +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_IPMI_HANDLER is not set +CONFIG_HW_RANDOM=y +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set +# CONFIG_RAW_DRIVER is not set +# CONFIG_TCG_TPM is not set +CONFIG_DEVPORT=y +CONFIG_I2C=m +CONFIG_I2C_BOARDINFO=y +# CONFIG_I2C_CHARDEV is not set + +# +# I2C Algorithms +# +# CONFIG_I2C_ALGOBIT is not set +# CONFIG_I2C_ALGOPCF is not set +# CONFIG_I2C_ALGOPCA is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI1563 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_PIIX4 is not set +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_I2C_SIMTEC is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_TAOS_EVM is not set +# CONFIG_I2C_STUB is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set + +# +# Miscellaneous I2C Chip support +# +# CONFIG_SENSORS_DS1337 is not set +# CONFIG_SENSORS_DS1374 is not set +# CONFIG_DS1682 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_PCF8574 is not set +# CONFIG_SENSORS_PCA9539 is not set +# CONFIG_SENSORS_PCF8591 is not set +# CONFIG_SENSORS_MAX6875 is not set +# CONFIG_SENSORS_TSL2550 is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_ALGO is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# SPI support +# +# CONFIG_SPI is not set +# CONFIG_SPI_MASTER is not set +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set +CONFIG_HWMON=y +# CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_AD7418 is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ADM1025 is not set +# CONFIG_SENSORS_ADM1026 is not set +# CONFIG_SENSORS_ADM1029 is not set +# CONFIG_SENSORS_ADM1031 is not set +# CONFIG_SENSORS_ADM9240 is not set +# CONFIG_SENSORS_ADT7470 is not set +# CONFIG_SENSORS_ATXP1 is not set +# CONFIG_SENSORS_DS1621 is not set +# CONFIG_SENSORS_I5K_AMB is not set +# CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set +# CONFIG_SENSORS_F75375S is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM63 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM77 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM80 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM87 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_LM92 is not set +# CONFIG_SENSORS_LM93 is not set +# CONFIG_SENSORS_MAX1619 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_PC87360 is not set +# CONFIG_SENSORS_PC87427 is not set +# CONFIG_SENSORS_SIS5595 is not set +# CONFIG_SENSORS_DME1737 is not set +# CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set +# CONFIG_SENSORS_SMSC47B397 is not set +# CONFIG_SENSORS_THMC50 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_VT1211 is not set +# CONFIG_SENSORS_VT8231 is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set +# CONFIG_SENSORS_W83792D is not set +# CONFIG_SENSORS_W83793 is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_SENSORS_W83627HF is not set +# CONFIG_SENSORS_W83627EHF is not set +# CONFIG_HWMON_DEBUG_CHIP is not set +CONFIG_WATCHDOG=y +# CONFIG_WATCHDOG_NOWAYOUT is not set + +# +# Watchdog Device Drivers +# +# CONFIG_SOFT_WATCHDOG is not set + +# +# PCI-based Watchdog Cards +# +# CONFIG_PCIPCWATCHDOG is not set +# CONFIG_WDTPCI is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set + +# +# Multifunction device drivers +# +# CONFIG_MFD_SM501 is not set + +# +# Multimedia devices +# +CONFIG_VIDEO_DEV=m +# CONFIG_VIDEO_V4L1 is not set +# CONFIG_VIDEO_V4L1_COMPAT is not set +CONFIG_VIDEO_V4L2=y +CONFIG_VIDEO_CAPTURE_DRIVERS=y +# CONFIG_VIDEO_ADV_DEBUG is not set +CONFIG_VIDEO_HELPER_CHIPS_AUTO=y +# CONFIG_VIDEO_VIVI is not set +# CONFIG_VIDEO_SAA5246A is not set +# CONFIG_VIDEO_SAA5249 is not set +# CONFIG_VIDEO_SAA7134 is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_CX23885 is not set +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_RADIO_ADAPTERS is not set +CONFIG_DVB_CORE=y +# CONFIG_DVB_CORE_ATTACH is not set +CONFIG_DVB_CAPTURE_DRIVERS=y + +# +# Supported SAA7146 based PCI Adapters +# + +# +# Supported FlexCopII (B2C2) Adapters +# +# CONFIG_DVB_B2C2_FLEXCOP is not set + +# +# Supported BT878 Adapters +# + +# +# Supported Pluto2 Adapters +# +# CONFIG_DVB_PLUTO2 is not set + +# +# Supported DVB Frontends +# + +# +# Customise DVB Frontends +# +# CONFIG_DVB_FE_CUSTOMISE is not set + +# +# DVB-S (satellite) frontends +# +# CONFIG_DVB_STV0299 is not set +# CONFIG_DVB_CX24110 is not set +# CONFIG_DVB_CX24123 is not set +# CONFIG_DVB_TDA8083 is not set +# CONFIG_DVB_MT312 is not set +# CONFIG_DVB_VES1X93 is not set +# CONFIG_DVB_S5H1420 is not set +# CONFIG_DVB_TDA10086 is not set + +# +# DVB-T (terrestrial) frontends +# +# CONFIG_DVB_SP8870 is not set +# CONFIG_DVB_SP887X is not set +# CONFIG_DVB_CX22700 is not set +# CONFIG_DVB_CX22702 is not set +# CONFIG_DVB_L64781 is not set +# CONFIG_DVB_TDA1004X is not set +# CONFIG_DVB_NXT6000 is not set +# CONFIG_DVB_MT352 is not set +# CONFIG_DVB_ZL10353 is not set +# CONFIG_DVB_DIB3000MB is not set +# CONFIG_DVB_DIB3000MC is not set +# CONFIG_DVB_DIB7000M is not set +# CONFIG_DVB_DIB7000P is not set + +# +# DVB-C (cable) frontends +# +# CONFIG_DVB_VES1820 is not set +# CONFIG_DVB_TDA10021 is not set +# CONFIG_DVB_TDA10023 is not set +# CONFIG_DVB_STV0297 is not set + +# +# ATSC (North American/Korean Terrestrial/Cable DTV) frontends +# +# CONFIG_DVB_NXT200X is not set +# CONFIG_DVB_OR51211 is not set +# CONFIG_DVB_OR51132 is not set +# CONFIG_DVB_BCM3510 is not set +# CONFIG_DVB_LGDT330X is not set +# CONFIG_DVB_S5H1409 is not set + +# +# Tuners/PLL support +# +# CONFIG_DVB_PLL is not set +# CONFIG_DVB_TDA826X is not set +# CONFIG_DVB_TDA827X is not set +# CONFIG_DVB_TUNER_QT1010 is not set +# CONFIG_DVB_TUNER_MT2060 is not set +# CONFIG_DVB_TUNER_MT2266 is not set +# CONFIG_DVB_TUNER_MT2131 is not set +# CONFIG_DVB_TUNER_DIB0070 is not set + +# +# Miscellaneous devices +# +# CONFIG_DVB_LNBP21 is not set +# CONFIG_DVB_ISL6421 is not set +# CONFIG_DVB_TUA6100 is not set +CONFIG_DAB=y + +# +# Graphics support +# +# CONFIG_DRM is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=y +CONFIG_FB=y +CONFIG_FIRMWARE_EDID=y +# CONFIG_FB_DDC is not set +# CONFIG_FB_CFB_FILLRECT is not set +# CONFIG_FB_CFB_COPYAREA is not set +# CONFIG_FB_CFB_IMAGEBLIT is not set +# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set +# CONFIG_FB_SYS_FILLRECT is not set +# CONFIG_FB_SYS_COPYAREA is not set +# CONFIG_FB_SYS_IMAGEBLIT is not set +# CONFIG_FB_SYS_FOPS is not set +CONFIG_FB_DEFERRED_IO=y +# CONFIG_FB_SVGALIB is not set +# CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set +CONFIG_FB_MODE_HELPERS=y +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S1D13XXX is not set +# CONFIG_FB_NVIDIA is not set +# CONFIG_FB_RIVA is not set +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_S3 is not set +# CONFIG_FB_SAVAGE is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_VT8623 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_ARK is not set +# CONFIG_FB_PM3 is not set +# CONFIG_FB_VIRTUAL is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set + +# +# Display device support +# +# CONFIG_DISPLAY_SUPPORT is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set +# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +CONFIG_FONT_8x16=y +# CONFIG_FONT_6x11 is not set +# CONFIG_FONT_7x14 is not set +# CONFIG_FONT_PEARL_8x8 is not set +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set +# CONFIG_FONT_10x18 is not set +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +# CONFIG_LOGO_LINUX_CLUT224 is not set +# CONFIG_LOGO_SUPERH_MONO is not set +# CONFIG_LOGO_SUPERH_VGA16 is not set +CONFIG_LOGO_SUPERH_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +# CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set +CONFIG_USB_SUPPORT=y +CONFIG_USB_ARCH_HAS_HCD=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +# CONFIG_USB is not set + +# +# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set +# CONFIG_MMC is not set +# CONFIG_NEW_LEDS is not set +# CONFIG_INFINIBAND is not set +# CONFIG_RTC_CLASS is not set + +# +# Userspace I/O +# +# CONFIG_UIO is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_FS_POSIX_ACL is not set +# CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set +# CONFIG_OCFS2_FS is not set +CONFIG_MINIX_FS=y +CONFIG_ROMFS_FS=y +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +# CONFIG_QUOTA is not set +CONFIG_DNOTIFY=y +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS 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=y +CONFIG_PROC_SYSCTL=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +# CONFIG_TMPFS_POSIX_ACL is not set +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +# CONFIG_CONFIGFS_FS is not set + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_HFSPLUS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL 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_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +# CONFIG_SUNRPC_BIND34 is not set +# 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=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +# CONFIG_MAC_PARTITION is not set +CONFIG_MSDOS_PARTITION=y +# CONFIG_BSD_DISKLABEL is not set +# CONFIG_MINIX_SUBPARTITION is not set +# CONFIG_SOLARIS_X86_PARTITION is not set +# CONFIG_UNIXWARE_DISKLABEL is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_KARMA_PARTITION is not set +# CONFIG_EFI_PARTITION is not set +# CONFIG_SYSV68_PARTITION is not set +# CONFIG_NLS is not set +# CONFIG_DLM is not set +CONFIG_INSTRUMENTATION=y +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set + +# +# Kernel hacking +# +CONFIG_TRACE_IRQFLAGS_SUPPORT=y +# CONFIG_PRINTK_TIME is not set +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set +CONFIG_DEBUG_FS=y +# CONFIG_HEADERS_CHECK is not set +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y +CONFIG_SCHEDSTATS=y +# CONFIG_TIMER_STATS is not set +# CONFIG_DEBUG_SLAB is not set +CONFIG_DEBUG_PREEMPT=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_DEBUG_MUTEXES is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set +# CONFIG_LOCK_STAT is not set +# CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set +# CONFIG_DEBUG_KOBJECT is not set +CONFIG_DEBUG_BUGVERBOSE=y +# CONFIG_DEBUG_INFO is not set +# CONFIG_DEBUG_VM is not set +# CONFIG_DEBUG_LIST is not set +# CONFIG_DEBUG_SG is not set +CONFIG_FRAME_POINTER=y +CONFIG_FORCED_INLINING=y +# CONFIG_BOOT_PRINTK_DELAY is not set +# CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_EARLY_SCIF_CONSOLE is not set +# CONFIG_DEBUG_BOOTMEM is not set +# CONFIG_DEBUG_STACK_USAGE is not set +# CONFIG_4KSTACKS is not set +CONFIG_SH64_PROC_ASIDS=y +CONFIG_SH64_SR_WATCH=y +# CONFIG_POOR_MANS_STRACE is not set +# CONFIG_SH_ALPHANUMERIC is not set +# CONFIG_SH_NO_BSS_INIT is not set + +# +# Security options +# +# CONFIG_KEYS is not set +# CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set +# CONFIG_CRYPTO is not set + +# +# Library routines +# +CONFIG_BITREVERSE=y +# CONFIG_CRC_CCITT is not set +# CONFIG_CRC16 is not set +# CONFIG_CRC_ITU_T is not set +CONFIG_CRC32=y +# CONFIG_CRC7 is not set +# CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y diff -puN arch/sh/configs/r7785rp_defconfig~git-sh arch/sh/configs/r7785rp_defconfig --- a/arch/sh/configs/r7785rp_defconfig~git-sh +++ a/arch/sh/configs/r7785rp_defconfig @@ -1,9 +1,10 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc2 -# Tue Nov 13 20:34:57 2007 +# Linux kernel version: 2.6.24-rc3 +# Fri Nov 23 14:03:57 2007 # CONFIG_SUPERH=y +CONFIG_SUPERH32=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_BUG=y CONFIG_GENERIC_FIND_NEXT_BIT=y @@ -39,6 +40,7 @@ CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set # CONFIG_TASKSTATS is not set # CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y @@ -130,6 +132,8 @@ CONFIG_CPU_SUBTYPE_SH7785=y # CONFIG_CPU_SUBTYPE_SHX3 is not set # CONFIG_CPU_SUBTYPE_SH7343 is not set # CONFIG_CPU_SUBTYPE_SH7722 is not set +# CONFIG_CPU_SUBTYPE_SH5_101 is not set +# CONFIG_CPU_SUBTYPE_SH5_103 is not set # # Memory management options @@ -139,7 +143,8 @@ CONFIG_MMU=y CONFIG_PAGE_OFFSET=0x80000000 CONFIG_MEMORY_START=0x08000000 CONFIG_MEMORY_SIZE=0x08000000 -# CONFIG_32BIT is not set +CONFIG_29BIT=y +# CONFIG_PMB is not set # CONFIG_X2TLB is not set CONFIG_VSYSCALL=y # CONFIG_NUMA is not set @@ -158,6 +163,7 @@ CONFIG_PAGE_SIZE_4KB=y CONFIG_HUGETLB_PAGE_SIZE_1MB=y # CONFIG_HUGETLB_PAGE_SIZE_4MB is not set # CONFIG_HUGETLB_PAGE_SIZE_64MB is not set +# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -701,6 +707,7 @@ CONFIG_DEVPORT=y # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set # CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_IT87 is not set diff -puN arch/sh/drivers/pci/Makefile~git-sh arch/sh/drivers/pci/Makefile --- a/arch/sh/drivers/pci/Makefile~git-sh +++ a/arch/sh/drivers/pci/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_SUBTYPE_SH7751) += pci- obj-$(CONFIG_CPU_SUBTYPE_SH7751R) += pci-sh7751.o ops-sh4.o obj-$(CONFIG_CPU_SUBTYPE_SH7780) += pci-sh7780.o ops-sh4.o obj-$(CONFIG_CPU_SUBTYPE_SH7785) += pci-sh7780.o ops-sh4.o +obj-$(CONFIG_CPU_SH5) += pci-sh5.o ops-sh5.o obj-$(CONFIG_SH_DREAMCAST) += ops-dreamcast.o fixups-dreamcast.o \ dma-dreamcast.o @@ -20,3 +21,4 @@ obj-$(CONFIG_SH_TITAN) += ops-titan.o obj-$(CONFIG_SH_LANDISK) += ops-landisk.o obj-$(CONFIG_SH_LBOX_RE2) += ops-lboxre2.o fixups-lboxre2.o obj-$(CONFIG_SH_7780_SOLUTION_ENGINE) += ops-se7780.o fixups-se7780.o +obj-$(CONFIG_SH_CAYMAN) += ops-cayman.o diff -puN /dev/null arch/sh/drivers/pci/ops-cayman.c --- /dev/null +++ a/arch/sh/drivers/pci/ops-cayman.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include "pci-sh5.h" + +static inline u8 bridge_swizzle(u8 pin, u8 slot) +{ + return (((pin - 1) + slot) % 4) + 1; +} + +int __init pcibios_map_platform_irq(struct pci_dev *dev, u8 slot, u8 pin) +{ + int result = -1; + + /* The complication here is that the PCI IRQ lines from the Cayman's 2 + 5V slots get into the CPU via a different path from the IRQ lines + from the 3 3.3V slots. Thus, we have to detect whether the card's + interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling' + at the point where we cross from 5V to 3.3V is not the normal case. + + The added complication is that we don't know that the 5V slots are + always bus 2, because a card containing a PCI-PCI bridge may be + plugged into a 3.3V slot, and this changes the bus numbering. + + Also, the Cayman has an intermediate PCI bus that goes a custom + expansion board header (and to the secondary bridge). This bus has + never been used in practice. + + The 1ary onboard PCI-PCI bridge is device 3 on bus 0 + The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of + the 1ary bridge. + */ + + struct slot_pin { + int slot; + int pin; + } path[4]; + int i=0; + + while (dev->bus->number > 0) { + + slot = path[i].slot = PCI_SLOT(dev->devfn); + pin = path[i].pin = bridge_swizzle(pin, slot); + dev = dev->bus->self; + i++; + if (i > 3) panic("PCI path to root bus too long!\n"); + } + + slot = PCI_SLOT(dev->devfn); + /* This is the slot on bus 0 through which the device is eventually + reachable. */ + + /* Now work back up. */ + if ((slot < 3) || (i == 0)) { + /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final + swizzle now. */ + result = IRQ_INTA + bridge_swizzle(pin, slot) - 1; + } else { + i--; + slot = path[i].slot; + pin = path[i].pin; + if (slot > 0) { + panic("PCI expansion bus device found - not handled!\n"); + } else { + if (i > 0) { + /* 5V slots */ + i--; + slot = path[i].slot; + pin = path[i].pin; + /* 'pin' was swizzled earlier wrt slot, don't do it again. */ + result = IRQ_P2INTA + (pin - 1); + } else { + /* IRQ for 2ary PCI-PCI bridge : unused */ + result = -1; + } + } + } + + return result; +} + +struct pci_channel board_pci_channels[] = { + { &sh5_pci_ops, NULL, NULL, 0, 0xff }, + { NULL, NULL, NULL, 0, 0 }, +}; +EXPORT_SYMBOL(board_pci_channels); + +int __init pcibios_init_platform(void) +{ + return sh5pci_init(__pa(memory_start), + __pa(memory_end) - __pa(memory_start)); +} diff -puN /dev/null arch/sh/drivers/pci/ops-sh5.c --- /dev/null +++ a/arch/sh/drivers/pci/ops-sh5.c @@ -0,0 +1,93 @@ +/* + * Support functions for the SH5 PCI hardware. + * + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci-sh5.h" + +static void __init pci_fixup_ide_bases(struct pci_dev *d) +{ + int i; + + /* + * PCI IDE controllers use non-standard I/O port decoding, respect it. + */ + if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) + return; + printk("PCI: IDE base address fixup for %s\n", pci_name(d)); + for(i=0; i<4; i++) { + struct resource *r = &d->resource[i]; + if ((r->start & ~0x80) == 0x374) { + r->start |= 2; + r->end = r->start; + } + } +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); + +char * __devinit pcibios_setup(char *str) +{ + return str; +} + +static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *val) +{ + SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); + + switch (size) { + case 1: + *val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3)); + break; + case 2: + *val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2)); + break; + case 4: + *val = SH5PCI_READ(PDR); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); + + switch (size) { + case 1: + SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); + break; + case 2: + SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); + break; + case 4: + SH5PCI_WRITE(PDR, val); + break; + } + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops sh5_pci_ops = { + .read = sh5pci_read, + .write = sh5pci_write, +}; diff -puN /dev/null arch/sh/drivers/pci/pci-sh5.c --- /dev/null +++ a/arch/sh/drivers/pci/pci-sh5.c @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Support functions for the SH5 PCI hardware. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pci-sh5.h" + +unsigned long pcicr_virt; +unsigned long PCI_IO_AREA; + +/* Rounds a number UP to the nearest power of two. Used for + * sizing the PCI window. + */ +static u32 __init r2p2(u32 num) +{ + int i = 31; + u32 tmp = num; + + if (num == 0) + return 0; + + do { + if (tmp & (1 << 31)) + break; + i--; + tmp <<= 1; + } while (i >= 0); + + tmp = 1 << i; + /* If the original number isn't a power of 2, round it up */ + if (tmp != num) + tmp <<= 1; + + return tmp; +} + +static irqreturn_t pcish5_err_irq(int irq, void *dev_id) +{ + struct pt_regs *regs = get_irq_regs(); + unsigned pci_int, pci_air, pci_cir, pci_aint; + + pci_int = SH5PCI_READ(INT); + pci_cir = SH5PCI_READ(CIR); + pci_air = SH5PCI_READ(AIR); + + if (pci_int) { + printk("PCI INTERRUPT (at %08llx)!\n", regs->pc); + printk("PCI INT -> 0x%x\n", pci_int & 0xffff); + printk("PCI AIR -> 0x%x\n", pci_air); + printk("PCI CIR -> 0x%x\n", pci_cir); + SH5PCI_WRITE(INT, ~0); + } + + pci_aint = SH5PCI_READ(AINT); + if (pci_aint) { + printk("PCI ARB INTERRUPT!\n"); + printk("PCI AINT -> 0x%x\n", pci_aint); + printk("PCI AIR -> 0x%x\n", pci_air); + printk("PCI CIR -> 0x%x\n", pci_cir); + SH5PCI_WRITE(AINT, ~0); + } + + return IRQ_HANDLED; +} + +static irqreturn_t pcish5_serr_irq(int irq, void *dev_id) +{ + printk("SERR IRQ\n"); + + return IRQ_NONE; +} + +int __init sh5pci_init(unsigned long memStart, unsigned long memSize) +{ + u32 lsr0; + u32 uval; + + if (request_irq(IRQ_ERR, pcish5_err_irq, + IRQF_DISABLED, "PCI Error",NULL) < 0) { + printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n"); + return -EINVAL; + } + + if (request_irq(IRQ_SERR, pcish5_serr_irq, + IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) { + printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n"); + return -EINVAL; + } + + pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR"); + if (!pcicr_virt) { + panic("Unable to remap PCICR\n"); + } + + PCI_IO_AREA = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO"); + if (!PCI_IO_AREA) { + panic("Unable to remap PCIIO\n"); + } + + /* Clear snoop registers */ + SH5PCI_WRITE(CSCR0, 0); + SH5PCI_WRITE(CSCR1, 0); + + /* Switch off interrupts */ + SH5PCI_WRITE(INTM, 0); + SH5PCI_WRITE(AINTM, 0); + SH5PCI_WRITE(PINTM, 0); + + /* Set bus active, take it out of reset */ + uval = SH5PCI_READ(CR); + + /* Set command Register */ + SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | + CR_PFCS | CR_BMAM); + + uval=SH5PCI_READ(CR); + + /* Allow it to be a master */ + /* NB - WE DISABLE I/O ACCESS to stop overlap */ + /* set WAIT bit to enable stepping, an attempt to improve stability */ + SH5PCI_WRITE_SHORT(CSR_CMD, + PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | + PCI_COMMAND_WAIT); + + /* + ** Set translation mapping memory in order to convert the address + ** used for the main bus, to the PCI internal address. + */ + SH5PCI_WRITE(MBR,0x40000000); + + /* Always set the max size 512M */ + SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024)); + + /* + ** I/O addresses are mapped at internal PCI specific address + ** as is described into the configuration bridge table. + ** These are changed to 0, to allow cards that have legacy + ** io such as vga to function correctly. We set the SH5 IOBAR to + ** 256K, which is a bit big as we can only have 64K of address space + */ + + SH5PCI_WRITE(IOBR,0x0); + + /* Set up a 256K window. Totally pointless waste of address space */ + SH5PCI_WRITE(IOBMR,0); + + /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. + * Ideally, we would want to map the I/O region somewhere, but it + * is so big this is not that easy! + */ + SH5PCI_WRITE(CSR_IBAR0,~0); + /* Set memory size value */ + memSize = memory_end - memory_start; + + /* Now we set up the mbars so the PCI bus can see the memory of + * the machine */ + if (memSize < (1024 * 1024)) { + printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%lx?\n", + memSize); + return -EINVAL; + } + + /* Set LSR 0 */ + lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : + ((r2p2(memSize) - 0x100000) | 0x1); + SH5PCI_WRITE(LSR0, lsr0); + + /* Set MBAR 0 */ + SH5PCI_WRITE(CSR_MBAR0, memory_start); + SH5PCI_WRITE(LAR0, memory_start); + + SH5PCI_WRITE(CSR_MBAR1,0); + SH5PCI_WRITE(LAR1,0); + SH5PCI_WRITE(LSR1,0); + + /* Enable the PCI interrupts on the device */ + SH5PCI_WRITE(INTM, ~0); + SH5PCI_WRITE(AINTM, ~0); + SH5PCI_WRITE(PINTM, ~0); + + return 0; +} + +void __devinit pcibios_fixup_bus(struct pci_bus *bus) +{ + struct pci_dev *dev = bus->self; + int i; + + if (dev) { + for (i= 0; i < 3; i++) { + bus->resource[i] = + &dev->resource[PCI_BRIDGE_RESOURCES+i]; + bus->resource[i]->name = bus->name; + } + bus->resource[0]->flags |= IORESOURCE_IO; + bus->resource[1]->flags |= IORESOURCE_MEM; + + /* For now, propagate host limits to the bus; + * we'll adjust them later. */ + bus->resource[0]->end = 64*1024 - 1 ; + bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1; + bus->resource[0]->start = PCIBIOS_MIN_IO; + bus->resource[1]->start = PCIBIOS_MIN_MEM; + + /* Turn off downstream PF memory address range by default */ + bus->resource[2]->start = 1024*1024; + bus->resource[2]->end = bus->resource[2]->start - 1; + } +} diff -puN /dev/null arch/sh/drivers/pci/pci-sh5.h --- /dev/null +++ a/arch/sh/drivers/pci/pci-sh5.h @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Definitions for the SH5 PCI hardware. + */ +#ifndef __PCI_SH5_H +#define __PCI_SH5_H + +/* Product ID */ +#define PCISH5_PID 0x350d + +/* vendor ID */ +#define PCISH5_VID 0x1054 + +/* Configuration types */ +#define ST_TYPE0 0x00 /* Configuration cycle type 0 */ +#define ST_TYPE1 0x01 /* Configuration cycle type 1 */ + +/* VCR data */ +#define PCISH5_VCR_STATUS 0x00 +#define PCISH5_VCR_VERSION 0x08 + +/* +** ICR register offsets and bits +*/ +#define PCISH5_ICR_CR 0x100 /* PCI control register values */ +#define CR_PBAM (1<<12) +#define CR_PFCS (1<<11) +#define CR_FTO (1<<10) +#define CR_PFE (1<<9) +#define CR_TBS (1<<8) +#define CR_SPUE (1<<7) +#define CR_BMAM (1<<6) +#define CR_HOST (1<<5) +#define CR_CLKEN (1<<4) +#define CR_SOCS (1<<3) +#define CR_IOCS (1<<2) +#define CR_RSTCTL (1<<1) +#define CR_CFINT (1<<0) +#define CR_LOCK_MASK 0xa5000000 + +#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */ +#define INT_MADIM (1<<2) + +#define PCISH5_ICR_LSR0 0X104 /* Local space register values */ +#define PCISH5_ICR_LSR1 0X108 /* Local space register values */ +#define PCISH5_ICR_LAR0 0x10c /* Local address register values */ +#define PCISH5_ICR_LAR1 0x110 /* Local address register values */ +#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */ +#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */ +#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */ +#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */ +#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */ +#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */ +#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */ +#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */ +#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */ +#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */ +#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */ +#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */ +#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */ +#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */ +#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */ +#define PCISH5_ICR_PDR 0x220 /* Pio data register values */ + +/* These are configs space registers */ +#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */ +#define PCISH5_ICR_CSR_DID 0x002 /* Device id */ +#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */ +#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */ +#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O base address register */ +#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */ +#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */ + +/* Base address of registers */ +#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000) +#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000) +/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */ + +extern unsigned long pcicr_virt; +/* Register selection macro */ +#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x)) +/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */ + +/* Write I/O functions */ +#define SH5PCI_WRITE(reg,val) ctrl_outl((u32)(val),PCISH5_ICR_REG(reg)) +#define SH5PCI_WRITE_SHORT(reg,val) ctrl_outw((u16)(val),PCISH5_ICR_REG(reg)) +#define SH5PCI_WRITE_BYTE(reg,val) ctrl_outb((u8)(val),PCISH5_ICR_REG(reg)) + +/* Read I/O functions */ +#define SH5PCI_READ(reg) ctrl_inl(PCISH5_ICR_REG(reg)) +#define SH5PCI_READ_SHORT(reg) ctrl_inw(PCISH5_ICR_REG(reg)) +#define SH5PCI_READ_BYTE(reg) ctrl_inb(PCISH5_ICR_REG(reg)) + +/* Set PCI config bits */ +#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000) + +/* Set PCI command register */ +#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) + +/* Size converters */ +#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18) +#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18) + +extern struct pci_ops sh5_pci_ops; + +/* arch/sh/drivers/pci/pci-sh5.c */ +int sh5pci_init(unsigned long memStart, unsigned long memSize); + +#endif /* __PCI_SH5_H */ diff -puN arch/sh/drivers/pci/pci.c~git-sh arch/sh/drivers/pci/pci.c --- a/arch/sh/drivers/pci/pci.c~git-sh +++ a/arch/sh/drivers/pci/pci.c @@ -71,7 +71,7 @@ subsys_initcall(pcibios_init); * Called after each bus is probed, but before its children * are examined. */ -void __devinit pcibios_fixup_bus(struct pci_bus *bus) +void __devinit __weak pcibios_fixup_bus(struct pci_bus *bus) { pci_read_bridge_bases(bus); } diff -puN arch/sh/kernel/Makefile~git-sh arch/sh/kernel/Makefile --- a/arch/sh/kernel/Makefile~git-sh +++ a/arch/sh/kernel/Makefile @@ -1,25 +1,5 @@ -# -# Makefile for the Linux/SuperH kernel. -# - -extra-y := head.o init_task.o vmlinux.lds - -obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process.o ptrace.o \ - semaphore.o setup.o signal.o sys_sh.o syscalls.o \ - time.o topology.o traps.o - -obj-y += cpu/ timers/ -obj-$(CONFIG_VSYSCALL) += vsyscall/ -obj-$(CONFIG_SMP) += smp.o -obj-$(CONFIG_CF_ENABLER) += cf-enabler.o -obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o -obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o -obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o -obj-$(CONFIG_MODULES) += sh_ksyms.o module.o -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o -obj-$(CONFIG_CRASH_DUMP) += crash_dump.o -obj-$(CONFIG_PM) += pm.o -obj-$(CONFIG_STACKTRACE) += stacktrace.o - -EXTRA_CFLAGS += -Werror +ifeq ($(CONFIG_SUPERH32),y) +include ${srctree}/arch/sh/kernel/Makefile_32 +else +include ${srctree}/arch/sh/kernel/Makefile_64 +endif diff -puN /dev/null arch/sh/kernel/Makefile_32 --- /dev/null +++ a/arch/sh/kernel/Makefile_32 @@ -0,0 +1,26 @@ +# +# Makefile for the Linux/SuperH kernel. +# + +extra-y := head_32.o init_task.o vmlinux.lds + +obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_32.o \ + ptrace_32.o semaphore.o setup.o signal_32.o sys_sh.o sys_sh32.o \ + syscalls_32.o time_32.o topology.o traps.o traps_32.o + +obj-y += cpu/ timers/ +obj-$(CONFIG_VSYSCALL) += vsyscall/ +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_CF_ENABLER) += cf-enabler.o +obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o +obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o +obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_MODULES) += sh_ksyms_32.o module.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o +obj-$(CONFIG_BINFMT_ELF) += dump_task.o + +EXTRA_CFLAGS += -Werror diff -puN /dev/null arch/sh/kernel/Makefile_64 --- /dev/null +++ a/arch/sh/kernel/Makefile_64 @@ -0,0 +1,22 @@ +extra-y := head_64.o init_task.o vmlinux.lds + +obj-y := debugtraps.o io.o io_generic.o irq.o machvec.o process_64.o \ + ptrace_64.o semaphore.o setup.o signal_64.o sys_sh.o sys_sh64.o \ + syscalls_64.o time_64.o topology.o traps.o traps_64.o + +obj-y += cpu/ timers/ +obj-$(CONFIG_VSYSCALL) += vsyscall/ +obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_CF_ENABLER) += cf-enabler.o +obj-$(CONFIG_SH_STANDARD_BIOS) += sh_bios.o +obj-$(CONFIG_SH_KGDB) += kgdb_stub.o kgdb_jmp.o +obj-$(CONFIG_SH_CPU_FREQ) += cpufreq.o +obj-$(CONFIG_MODULES) += sh_ksyms_64.o module.o +obj-$(CONFIG_EARLY_PRINTK) += early_printk.o +obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o +obj-$(CONFIG_CRASH_DUMP) += crash_dump.o +obj-$(CONFIG_PM) += pm.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o +obj-$(CONFIG_BINFMT_ELF) += dump_task.o + +EXTRA_CFLAGS += -Werror diff -puN arch/sh/kernel/cpu/Makefile~git-sh arch/sh/kernel/cpu/Makefile --- a/arch/sh/kernel/cpu/Makefile~git-sh +++ a/arch/sh/kernel/cpu/Makefile @@ -6,8 +6,14 @@ obj-$(CONFIG_CPU_SH2) = sh2/ obj-$(CONFIG_CPU_SH2A) = sh2a/ obj-$(CONFIG_CPU_SH3) = sh3/ obj-$(CONFIG_CPU_SH4) = sh4/ +obj-$(CONFIG_CPU_SH5) = sh5/ + +# Special cases for family ancestry. + obj-$(CONFIG_CPU_SH4A) += sh4a/ +# Common interfaces. + obj-$(CONFIG_UBC_WAKEUP) += ubc.o obj-$(CONFIG_SH_ADC) += adc.o diff -puN arch/sh/kernel/cpu/init.c~git-sh arch/sh/kernel/cpu/init.c --- a/arch/sh/kernel/cpu/init.c~git-sh +++ a/arch/sh/kernel/cpu/init.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -20,9 +21,12 @@ #include #include #include +#include #include -#include #include +#ifdef CONFIG_SUPERH32 +#include +#endif /* * Generic wrapper for command line arguments to disable on-chip @@ -61,25 +65,12 @@ static void __init speculative_execution /* * Generic first-level cache init */ -static void __init cache_init(void) +#ifdef CONFIG_SUPERH32 +static void __uses_jump_to_uncached cache_init(void) { unsigned long ccr, flags; - /* First setup the rest of the I-cache info */ - current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr - - current_cpu_data.icache.linesz; - - current_cpu_data.icache.way_size = current_cpu_data.icache.sets * - current_cpu_data.icache.linesz; - - /* And the D-cache too */ - current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr - - current_cpu_data.dcache.linesz; - - current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * - current_cpu_data.dcache.linesz; - - jump_to_P2(); + jump_to_uncached(); ccr = ctrl_inl(CCR); /* @@ -156,7 +147,31 @@ static void __init cache_init(void) #endif ctrl_outl(flags, CCR); - back_to_P1(); + back_to_cached(); +} +#else +#define cache_init() do { } while (0) +#endif + +#define CSHAPE(totalsize, linesize, assoc) \ + ((totalsize & ~0xff) | (linesize << 4) | assoc) + +#define CACHE_DESC_SHAPE(desc) \ + CSHAPE((desc).way_size * (desc).ways, ilog2((desc).linesz), (desc).ways) + +static void detect_cache_shape(void) +{ + l1d_cache_shape = CACHE_DESC_SHAPE(current_cpu_data.dcache); + + if (current_cpu_data.dcache.flags & SH_CACHE_COMBINED) + l1i_cache_shape = l1d_cache_shape; + else + l1i_cache_shape = CACHE_DESC_SHAPE(current_cpu_data.icache); + + if (current_cpu_data.flags & CPU_HAS_L2_CACHE) + l2_cache_shape = CACHE_DESC_SHAPE(current_cpu_data.scache); + else + l2_cache_shape = -1; /* No S-cache */ } #ifdef CONFIG_SH_DSP @@ -228,14 +243,32 @@ asmlinkage void __cpuinit sh_cpu_init(vo if (current_cpu_data.type == CPU_SH_NONE) panic("Unknown CPU"); + /* First setup the rest of the I-cache info */ + current_cpu_data.icache.entry_mask = current_cpu_data.icache.way_incr - + current_cpu_data.icache.linesz; + + current_cpu_data.icache.way_size = current_cpu_data.icache.sets * + current_cpu_data.icache.linesz; + + /* And the D-cache too */ + current_cpu_data.dcache.entry_mask = current_cpu_data.dcache.way_incr - + current_cpu_data.dcache.linesz; + + current_cpu_data.dcache.way_size = current_cpu_data.dcache.sets * + current_cpu_data.dcache.linesz; + /* Init the cache */ cache_init(); - if (raw_smp_processor_id() == 0) + if (raw_smp_processor_id() == 0) { shm_align_mask = max_t(unsigned long, current_cpu_data.dcache.way_size - 1, PAGE_SIZE - 1); + /* Boot CPU sets the cache shape */ + detect_cache_shape(); + } + /* Disable the FPU */ if (fpu_disabled) { printk("FPU Disabled\n"); @@ -273,7 +306,10 @@ asmlinkage void __cpuinit sh_cpu_init(vo * like PTRACE_SINGLESTEP or doing hardware watchpoints in GDB. So .. * we wake it up and hope that all is well. */ +#ifdef CONFIG_SUPERH32 if (raw_smp_processor_id() == 0) ubc_wakeup(); +#endif + speculative_execution_init(); } diff -puN arch/sh/kernel/cpu/irq/Makefile~git-sh arch/sh/kernel/cpu/irq/Makefile --- a/arch/sh/kernel/cpu/irq/Makefile~git-sh +++ a/arch/sh/kernel/cpu/irq/Makefile @@ -1,7 +1,9 @@ # # Makefile for the Linux/SuperH CPU-specifc IRQ handlers. # -obj-y += imask.o intc.o +obj-y += intc.o +obj-$(CONFIG_SUPERH32) += imask.o +obj-$(CONFIG_CPU_SH5) += intc-sh5.o obj-$(CONFIG_CPU_HAS_IPR_IRQ) += ipr.o obj-$(CONFIG_CPU_HAS_MASKREG_IRQ) += maskreg.o diff -puN /dev/null arch/sh/kernel/cpu/irq/intc-sh5.c --- /dev/null +++ a/arch/sh/kernel/cpu/irq/intc-sh5.c @@ -0,0 +1,257 @@ +/* + * arch/sh/kernel/cpu/irq/intc-sh5.c + * + * Interrupt Controller support for SH5 INTC. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * + * Per-interrupt selective. IRLM=0 (Fixed priority) is not + * supported being useless without a cascaded interrupt + * controller. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Maybe the generic Peripheral block could move to a more + * generic include file. INTC Block will be defined here + * and only here to make INTC self-contained in a single + * file. + */ +#define INTC_BLOCK_OFFSET 0x01000000 + +/* Base */ +#define INTC_BASE PHYS_PERIPHERAL_BLOCK + \ + INTC_BLOCK_OFFSET + +/* Address */ +#define INTC_ICR_SET (intc_virt + 0x0) +#define INTC_ICR_CLEAR (intc_virt + 0x8) +#define INTC_INTPRI_0 (intc_virt + 0x10) +#define INTC_INTSRC_0 (intc_virt + 0x50) +#define INTC_INTSRC_1 (intc_virt + 0x58) +#define INTC_INTREQ_0 (intc_virt + 0x60) +#define INTC_INTREQ_1 (intc_virt + 0x68) +#define INTC_INTENB_0 (intc_virt + 0x70) +#define INTC_INTENB_1 (intc_virt + 0x78) +#define INTC_INTDSB_0 (intc_virt + 0x80) +#define INTC_INTDSB_1 (intc_virt + 0x88) + +#define INTC_ICR_IRLM 0x1 +#define INTC_INTPRI_PREGS 8 /* 8 Priority Registers */ +#define INTC_INTPRI_PPREG 8 /* 8 Priorities per Register */ + + +/* + * Mapper between the vector ordinal and the IRQ number + * passed to kernel/device drivers. + */ +int intc_evt_to_irq[(0xE20/0x20)+1] = { + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x000 - 0x0E0 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x100 - 0x1E0 */ + 0, 0, 0, 0, 0, 1, 0, 0, /* 0x200 - 0x2E0 */ + 2, 0, 0, 3, 0, 0, 0, -1, /* 0x300 - 0x3E0 */ + 32, 33, 34, 35, 36, 37, 38, -1, /* 0x400 - 0x4E0 */ + -1, -1, -1, 63, -1, -1, -1, -1, /* 0x500 - 0x5E0 */ + -1, -1, 18, 19, 20, 21, 22, -1, /* 0x600 - 0x6E0 */ + 39, 40, 41, 42, -1, -1, -1, -1, /* 0x700 - 0x7E0 */ + 4, 5, 6, 7, -1, -1, -1, -1, /* 0x800 - 0x8E0 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0x900 - 0x9E0 */ + 12, 13, 14, 15, 16, 17, -1, -1, /* 0xA00 - 0xAE0 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB00 - 0xBE0 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC00 - 0xCE0 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD00 - 0xDE0 */ + -1, -1 /* 0xE00 - 0xE20 */ +}; + +/* + * Opposite mapper. + */ +static int IRQ_to_vectorN[NR_INTC_IRQS] = { + 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ + -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ + 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ + 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ + 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ + -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ + +}; + +static unsigned long intc_virt; + +static unsigned int startup_intc_irq(unsigned int irq); +static void shutdown_intc_irq(unsigned int irq); +static void enable_intc_irq(unsigned int irq); +static void disable_intc_irq(unsigned int irq); +static void mask_and_ack_intc(unsigned int); +static void end_intc_irq(unsigned int irq); + +static struct hw_interrupt_type intc_irq_type = { + .typename = "INTC", + .startup = startup_intc_irq, + .shutdown = shutdown_intc_irq, + .enable = enable_intc_irq, + .disable = disable_intc_irq, + .ack = mask_and_ack_intc, + .end = end_intc_irq +}; + +static int irlm; /* IRL mode */ + +static unsigned int startup_intc_irq(unsigned int irq) +{ + enable_intc_irq(irq); + return 0; /* never anything pending */ +} + +static void shutdown_intc_irq(unsigned int irq) +{ + disable_intc_irq(irq); +} + +static void enable_intc_irq(unsigned int irq) +{ + unsigned long reg; + unsigned long bitmask; + + if ((irq <= IRQ_IRL3) && (irlm == NO_PRIORITY)) + printk("Trying to use straight IRL0-3 with an encoding platform.\n"); + + if (irq < 32) { + reg = INTC_INTENB_0; + bitmask = 1 << irq; + } else { + reg = INTC_INTENB_1; + bitmask = 1 << (irq - 32); + } + + ctrl_outl(bitmask, reg); +} + +static void disable_intc_irq(unsigned int irq) +{ + unsigned long reg; + unsigned long bitmask; + + if (irq < 32) { + reg = INTC_INTDSB_0; + bitmask = 1 << irq; + } else { + reg = INTC_INTDSB_1; + bitmask = 1 << (irq - 32); + } + + ctrl_outl(bitmask, reg); +} + +static void mask_and_ack_intc(unsigned int irq) +{ + disable_intc_irq(irq); +} + +static void end_intc_irq(unsigned int irq) +{ + enable_intc_irq(irq); +} + +/* For future use, if we ever support IRLM=0) */ +void make_intc_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].chip = &intc_irq_type; + disable_intc_irq(irq); +} + +#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) +int intc_irq_describe(char* p, int irq) +{ + if (irq < NR_INTC_IRQS) + return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20); + else + return 0; +} +#endif + +void __init plat_irq_setup(void) +{ + unsigned long long __dummy0, __dummy1=~0x00000000100000f0; + unsigned long reg; + unsigned long data; + int i; + + intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); + if (!intc_virt) { + panic("Unable to remap INTC\n"); + } + + + /* Set default: per-line enable/disable, priority driven ack/eoi */ + for (i = 0; i < NR_INTC_IRQS; i++) { + if (platform_int_priority[i] != NO_PRIORITY) { + irq_desc[i].chip = &intc_irq_type; + } + } + + + /* Disable all interrupts and set all priorities to 0 to avoid trouble */ + ctrl_outl(-1, INTC_INTDSB_0); + ctrl_outl(-1, INTC_INTDSB_1); + + for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8) + ctrl_outl( NO_PRIORITY, reg); + + + /* Set IRLM */ + /* If all the priorities are set to 'no priority', then + * assume we are using encoded mode. + */ + irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ + platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; + + if (irlm == NO_PRIORITY) { + /* IRLM = 0 */ + reg = INTC_ICR_CLEAR; + i = IRQ_INTA; + printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); + } else { + /* IRLM = 1 */ + reg = INTC_ICR_SET; + i = IRQ_IRL0; + } + ctrl_outl(INTC_ICR_IRLM, reg); + + /* Set interrupt priorities according to platform description */ + for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { + data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); + if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { + /* Upon the 7th, set Priority Register */ + ctrl_outl(data, reg); + data = 0; + reg += 8; + } + } + + /* + * And now let interrupts come in. + * sti() is not enough, we need to + * lower priority, too. + */ + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); +} diff -puN arch/sh/kernel/cpu/sh2/entry.S~git-sh arch/sh/kernel/cpu/sh2/entry.S --- a/arch/sh/kernel/cpu/sh2/entry.S~git-sh +++ a/arch/sh/kernel/cpu/sh2/entry.S @@ -149,6 +149,14 @@ ENTRY(exception_handler) mov #32,r8 cmp/hs r8,r9 bt trap_entry ! 64 > vec >= 32 is trap + +#if defined(CONFIG_SH_FPU) + mov #13,r8 + cmp/eq r8,r9 + bt 10f ! fpu + nop +#endif + mov.l 4f,r8 mov r9,r4 shll2 r9 @@ -158,6 +166,10 @@ ENTRY(exception_handler) cmp/eq r9,r8 bf 3f mov.l 8f,r8 ! unhandled exception +#if defined(CONFIG_SH_FPU) +10: + mov.l 9f, r8 ! unhandled exception +#endif 3: mov.l 5f,r10 jmp @r8 @@ -177,7 +189,10 @@ interrupt_entry: 6: .long ret_from_irq 7: .long do_IRQ 8: .long do_exception_error - +#ifdef CONFIG_SH_FPU +9: .long fpu_error_trap_handler +#endif + trap_entry: mov #0x30,r8 cmp/ge r8,r9 ! vector 0x20-0x2f is systemcall @@ -250,7 +265,7 @@ ENTRY(sh_bios_handler) 1: .long gdb_vbr_vector #endif /* CONFIG_SH_STANDARD_BIOS */ -ENTRY(address_error_handler) +ENTRY(address_error_trap_handler) mov r15,r4 ! regs add #4,r4 mov #OFF_PC,r0 diff -puN arch/sh/kernel/cpu/sh2a/Makefile~git-sh arch/sh/kernel/cpu/sh2a/Makefile --- a/arch/sh/kernel/cpu/sh2a/Makefile~git-sh +++ a/arch/sh/kernel/cpu/sh2a/Makefile @@ -6,4 +6,8 @@ obj-y := common.o probe.o opcode_helper. common-y += $(addprefix ../sh2/, ex.o entry.o) +obj-$(CONFIG_SH_FPU) += fpu.o + obj-$(CONFIG_CPU_SUBTYPE_SH7206) += setup-sh7206.o clock-sh7206.o +obj-$(CONFIG_CPU_SUBTYPE_SH7203) += setup-sh7203.o clock-sh7203.o +obj-$(CONFIG_CPU_SUBTYPE_SH7263) += setup-sh7203.o clock-sh7203.o diff -puN /dev/null arch/sh/kernel/cpu/sh2a/clock-sh7203.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh2a/clock-sh7203.c @@ -0,0 +1,89 @@ +/* + * arch/sh/kernel/cpu/sh2a/clock-sh7203.c + * + * SH7203 support for the clock framework + * + * Copyright (C) 2007 Kieran Bingham (MPC-Data Ltd) + * + * Based on clock-sh7263.c + * Copyright (C) 2006 Yoshinori Sato + * + * Based on clock-sh4.c + * Copyright (C) 2005 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +const static int pll1rate[]={8,12,16,0}; +const static int pfc_divisors[]={1,2,3,4,6,8,12}; +#define ifc_divisors pfc_divisors + +#if (CONFIG_SH_CLK_MD == 0) +#define PLL2 (1) +#elif (CONFIG_SH_CLK_MD == 1) +#define PLL2 (2) +#elif (CONFIG_SH_CLK_MD == 2) +#define PLL2 (4) +#elif (CONFIG_SH_CLK_MD == 3) +#define PLL2 (4) +#else +#error "Illegal Clock Mode!" +#endif + +static void master_clk_init(struct clk *clk) +{ + clk->rate *= pll1rate[(ctrl_inw(FREQCR) >> 8) & 0x0003] * PLL2 ; +} + +static struct clk_ops sh7203_master_clk_ops = { + .init = master_clk_init, +}; + +static void module_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx]; +} + +static struct clk_ops sh7203_module_clk_ops = { + .recalc = module_clk_recalc, +}; + +static void bus_clk_recalc(struct clk *clk) +{ + int idx = (ctrl_inw(FREQCR) & 0x0007); + clk->rate = clk->parent->rate / pfc_divisors[idx-2]; +} + +static struct clk_ops sh7203_bus_clk_ops = { + .recalc = bus_clk_recalc, +}; + +static void cpu_clk_recalc(struct clk *clk) +{ + clk->rate = clk->parent->rate; +} + +static struct clk_ops sh7203_cpu_clk_ops = { + .recalc = cpu_clk_recalc, +}; + +static struct clk_ops *sh7203_clk_ops[] = { + &sh7203_master_clk_ops, + &sh7203_module_clk_ops, + &sh7203_bus_clk_ops, + &sh7203_cpu_clk_ops, +}; + +void __init arch_init_clk_ops(struct clk_ops **ops, int idx) +{ + if (idx < ARRAY_SIZE(sh7203_clk_ops)) + *ops = sh7203_clk_ops[idx]; +} diff -puN /dev/null arch/sh/kernel/cpu/sh2a/fpu.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh2a/fpu.c @@ -0,0 +1,633 @@ +/* + * Save/restore floating point context for signal handlers. + * + * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * FIXME! These routines can be optimized in big endian case. + */ +#include +#include +#include +#include + +/* The PR (precision) bit in the FP Status Register must be clear when + * an frchg instruction is executed, otherwise the instruction is undefined. + * Executing frchg with PR set causes a trap on some SH4 implementations. + */ + +#define FPSCR_RCHG 0x00000000 + + +/* + * Save FPU registers onto task structure. + * Assume called with FPU enabled (SR.FD=0). + */ +void +save_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + unsigned long dummy; + + clear_tsk_thread_flag(tsk, TIF_USEDFPU); + enable_fpu(); + asm volatile("sts.l fpul, @-%0\n\t" + "sts.l fpscr, @-%0\n\t" + "fmov.s fr15, @-%0\n\t" + "fmov.s fr14, @-%0\n\t" + "fmov.s fr13, @-%0\n\t" + "fmov.s fr12, @-%0\n\t" + "fmov.s fr11, @-%0\n\t" + "fmov.s fr10, @-%0\n\t" + "fmov.s fr9, @-%0\n\t" + "fmov.s fr8, @-%0\n\t" + "fmov.s fr7, @-%0\n\t" + "fmov.s fr6, @-%0\n\t" + "fmov.s fr5, @-%0\n\t" + "fmov.s fr4, @-%0\n\t" + "fmov.s fr3, @-%0\n\t" + "fmov.s fr2, @-%0\n\t" + "fmov.s fr1, @-%0\n\t" + "fmov.s fr0, @-%0\n\t" + "lds %3, fpscr\n\t" + : "=r" (dummy) + : "0" ((char *)(&tsk->thread.fpu.hard.status)), + "r" (FPSCR_RCHG), + "r" (FPSCR_INIT) + : "memory"); + + disable_fpu(); + release_fpu(regs); +} + +static void +restore_fpu(struct task_struct *tsk) +{ + unsigned long dummy; + + enable_fpu(); + asm volatile("fmov.s @%0+, fr0\n\t" + "fmov.s @%0+, fr1\n\t" + "fmov.s @%0+, fr2\n\t" + "fmov.s @%0+, fr3\n\t" + "fmov.s @%0+, fr4\n\t" + "fmov.s @%0+, fr5\n\t" + "fmov.s @%0+, fr6\n\t" + "fmov.s @%0+, fr7\n\t" + "fmov.s @%0+, fr8\n\t" + "fmov.s @%0+, fr9\n\t" + "fmov.s @%0+, fr10\n\t" + "fmov.s @%0+, fr11\n\t" + "fmov.s @%0+, fr12\n\t" + "fmov.s @%0+, fr13\n\t" + "fmov.s @%0+, fr14\n\t" + "fmov.s @%0+, fr15\n\t" + "lds.l @%0+, fpscr\n\t" + "lds.l @%0+, fpul\n\t" + : "=r" (dummy) + : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG) + : "memory"); + disable_fpu(); +} + +/* + * Load the FPU with signalling NANS. This bit pattern we're using + * has the property that no matter wether considered as single or as + * double precission represents signaling NANS. + */ + +static void +fpu_init(void) +{ + enable_fpu(); + asm volatile("lds %0, fpul\n\t" + "fsts fpul, fr0\n\t" + "fsts fpul, fr1\n\t" + "fsts fpul, fr2\n\t" + "fsts fpul, fr3\n\t" + "fsts fpul, fr4\n\t" + "fsts fpul, fr5\n\t" + "fsts fpul, fr6\n\t" + "fsts fpul, fr7\n\t" + "fsts fpul, fr8\n\t" + "fsts fpul, fr9\n\t" + "fsts fpul, fr10\n\t" + "fsts fpul, fr11\n\t" + "fsts fpul, fr12\n\t" + "fsts fpul, fr13\n\t" + "fsts fpul, fr14\n\t" + "fsts fpul, fr15\n\t" + "lds %2, fpscr\n\t" + : /* no output */ + : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); + disable_fpu(); +} + +/* + * Emulate arithmetic ops on denormalized number for some FPU insns. + */ + +/* denormalized float * float */ +static int denormal_mulf(int hx, int hy) +{ + unsigned int ix, iy; + unsigned long long m, n; + int exp, w; + + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + if (iy < 0x00800000 || ix == 0) + return ((hx ^ hy) & 0x80000000); + + exp = (iy & 0x7f800000) >> 23; + ix &= 0x007fffff; + iy = (iy & 0x007fffff) | 0x00800000; + m = (unsigned long long)ix * iy; + n = m; + w = -1; + while (n) { n >>= 1; w++; } + + /* FIXME: use guard bits */ + exp += w - 126 - 46; + if (exp > 0) + ix = ((int) (m >> (w - 23)) & 0x007fffff) | (exp << 23); + else if (exp + 22 >= 0) + ix = (int) (m >> (w - 22 - exp)) & 0x007fffff; + else + ix = 0; + + ix |= (hx ^ hy) & 0x80000000; + return ix; +} + +/* denormalized double * double */ +static void mult64(unsigned long long x, unsigned long long y, + unsigned long long *highp, unsigned long long *lowp) +{ + unsigned long long sub0, sub1, sub2, sub3; + unsigned long long high, low; + + sub0 = (x >> 32) * (unsigned long) (y >> 32); + sub1 = (x & 0xffffffffLL) * (unsigned long) (y >> 32); + sub2 = (x >> 32) * (unsigned long) (y & 0xffffffffLL); + sub3 = (x & 0xffffffffLL) * (unsigned long) (y & 0xffffffffLL); + low = sub3; + high = 0LL; + sub3 += (sub1 << 32); + if (low > sub3) + high++; + low = sub3; + sub3 += (sub2 << 32); + if (low > sub3) + high++; + low = sub3; + high += (sub1 >> 32) + (sub2 >> 32); + high += sub0; + *lowp = low; + *highp = high; +} + +static inline long long rshift64(unsigned long long mh, + unsigned long long ml, int n) +{ + if (n >= 64) + return mh >> (n - 64); + return (mh << (64 - n)) | (ml >> n); +} + +static long long denormal_muld(long long hx, long long hy) +{ + unsigned long long ix, iy; + unsigned long long mh, ml, nh, nl; + int exp, w; + + ix = hx & 0x7fffffffffffffffLL; + iy = hy & 0x7fffffffffffffffLL; + if (iy < 0x0010000000000000LL || ix == 0) + return ((hx ^ hy) & 0x8000000000000000LL); + + exp = (iy & 0x7ff0000000000000LL) >> 52; + ix &= 0x000fffffffffffffLL; + iy = (iy & 0x000fffffffffffffLL) | 0x0010000000000000LL; + mult64(ix, iy, &mh, &ml); + nh = mh; + nl = ml; + w = -1; + if (nh) { + while (nh) { nh >>= 1; w++;} + w += 64; + } else + while (nl) { nl >>= 1; w++;} + + /* FIXME: use guard bits */ + exp += w - 1022 - 52 * 2; + if (exp > 0) + ix = (rshift64(mh, ml, w - 52) & 0x000fffffffffffffLL) + | ((long long)exp << 52); + else if (exp + 51 >= 0) + ix = rshift64(mh, ml, w - 51 - exp) & 0x000fffffffffffffLL; + else + ix = 0; + + ix |= (hx ^ hy) & 0x8000000000000000LL; + return ix; +} + +/* ix - iy where iy: denormal and ix, iy >= 0 */ +static int denormal_subf1(unsigned int ix, unsigned int iy) +{ + int frac; + int exp; + + if (ix < 0x00800000) + return ix - iy; + + exp = (ix & 0x7f800000) >> 23; + if (exp - 1 > 31) + return ix; + iy >>= exp - 1; + if (iy == 0) + return ix; + + frac = (ix & 0x007fffff) | 0x00800000; + frac -= iy; + while (frac < 0x00800000) { + if (--exp == 0) + return frac; + frac <<= 1; + } + + return (exp << 23) | (frac & 0x007fffff); +} + +/* ix + iy where iy: denormal and ix, iy >= 0 */ +static int denormal_addf1(unsigned int ix, unsigned int iy) +{ + int frac; + int exp; + + if (ix < 0x00800000) + return ix + iy; + + exp = (ix & 0x7f800000) >> 23; + if (exp - 1 > 31) + return ix; + iy >>= exp - 1; + if (iy == 0) + return ix; + + frac = (ix & 0x007fffff) | 0x00800000; + frac += iy; + if (frac >= 0x01000000) { + frac >>= 1; + ++exp; + } + + return (exp << 23) | (frac & 0x007fffff); +} + +static int denormal_addf(int hx, int hy) +{ + unsigned int ix, iy; + int sign; + + if ((hx ^ hy) & 0x80000000) { + sign = hx & 0x80000000; + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + if (iy < 0x00800000) { + ix = denormal_subf1(ix, iy); + if (ix < 0) { + ix = -ix; + sign ^= 0x80000000; + } + } else { + ix = denormal_subf1(iy, ix); + sign ^= 0x80000000; + } + } else { + sign = hx & 0x80000000; + ix = hx & 0x7fffffff; + iy = hy & 0x7fffffff; + if (iy < 0x00800000) + ix = denormal_addf1(ix, iy); + else + ix = denormal_addf1(iy, ix); + } + + return sign | ix; +} + +/* ix - iy where iy: denormal and ix, iy >= 0 */ +static long long denormal_subd1(unsigned long long ix, unsigned long long iy) +{ + long long frac; + int exp; + + if (ix < 0x0010000000000000LL) + return ix - iy; + + exp = (ix & 0x7ff0000000000000LL) >> 52; + if (exp - 1 > 63) + return ix; + iy >>= exp - 1; + if (iy == 0) + return ix; + + frac = (ix & 0x000fffffffffffffLL) | 0x0010000000000000LL; + frac -= iy; + while (frac < 0x0010000000000000LL) { + if (--exp == 0) + return frac; + frac <<= 1; + } + + return ((long long)exp << 52) | (frac & 0x000fffffffffffffLL); +} + +/* ix + iy where iy: denormal and ix, iy >= 0 */ +static long long denormal_addd1(unsigned long long ix, unsigned long long iy) +{ + long long frac; + long long exp; + + if (ix < 0x0010000000000000LL) + return ix + iy; + + exp = (ix & 0x7ff0000000000000LL) >> 52; + if (exp - 1 > 63) + return ix; + iy >>= exp - 1; + if (iy == 0) + return ix; + + frac = (ix & 0x000fffffffffffffLL) | 0x0010000000000000LL; + frac += iy; + if (frac >= 0x0020000000000000LL) { + frac >>= 1; + ++exp; + } + + return (exp << 52) | (frac & 0x000fffffffffffffLL); +} + +static long long denormal_addd(long long hx, long long hy) +{ + unsigned long long ix, iy; + long long sign; + + if ((hx ^ hy) & 0x8000000000000000LL) { + sign = hx & 0x8000000000000000LL; + ix = hx & 0x7fffffffffffffffLL; + iy = hy & 0x7fffffffffffffffLL; + if (iy < 0x0010000000000000LL) { + ix = denormal_subd1(ix, iy); + if (ix < 0) { + ix = -ix; + sign ^= 0x8000000000000000LL; + } + } else { + ix = denormal_subd1(iy, ix); + sign ^= 0x8000000000000000LL; + } + } else { + sign = hx & 0x8000000000000000LL; + ix = hx & 0x7fffffffffffffffLL; + iy = hy & 0x7fffffffffffffffLL; + if (iy < 0x0010000000000000LL) + ix = denormal_addd1(ix, iy); + else + ix = denormal_addd1(iy, ix); + } + + return sign | ix; +} + +/** + * denormal_to_double - Given denormalized float number, + * store double float + * + * @fpu: Pointer to sh_fpu_hard structure + * @n: Index to FP register + */ +static void +denormal_to_double (struct sh_fpu_hard_struct *fpu, int n) +{ + unsigned long du, dl; + unsigned long x = fpu->fpul; + int exp = 1023 - 126; + + if (x != 0 && (x & 0x7f800000) == 0) { + du = (x & 0x80000000); + while ((x & 0x00800000) == 0) { + x <<= 1; + exp--; + } + x &= 0x007fffff; + du |= (exp << 20) | (x >> 3); + dl = x << 29; + + fpu->fp_regs[n] = du; + fpu->fp_regs[n+1] = dl; + } +} + +/** + * ieee_fpe_handler - Handle denormalized number exception + * + * @regs: Pointer to register structure + * + * Returns 1 when it's handled (should not cause exception). + */ +static int +ieee_fpe_handler (struct pt_regs *regs) +{ + unsigned short insn = *(unsigned short *) regs->pc; + unsigned short finsn; + unsigned long nextpc; + int nib[4] = { + (insn >> 12) & 0xf, + (insn >> 8) & 0xf, + (insn >> 4) & 0xf, + insn & 0xf}; + + if (nib[0] == 0xb || + (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ + regs->pr = regs->pc + 4; + if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ + nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ + if (regs->sr & 1) + nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); + else + nextpc = regs->pc + 4; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ + if (regs->sr & 1) + nextpc = regs->pc + 4; + else + nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x4 && nib[3] == 0xb && + (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ + nextpc = regs->regs[nib[1]]; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (nib[0] == 0x0 && nib[3] == 0x3 && + (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ + nextpc = regs->pc + 4 + regs->regs[nib[1]]; + finsn = *(unsigned short *) (regs->pc + 2); + } else if (insn == 0x000b) { /* rts */ + nextpc = regs->pr; + finsn = *(unsigned short *) (regs->pc + 2); + } else { + nextpc = regs->pc + 2; + finsn = insn; + } + +#define FPSCR_FPU_ERROR (1 << 17) + + if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ + struct task_struct *tsk = current; + + if ((tsk->thread.fpu.hard.fpscr & FPSCR_FPU_ERROR)) { + /* FPU error */ + denormal_to_double (&tsk->thread.fpu.hard, + (finsn >> 8) & 0xf); + } else + return 0; + + regs->pc = nextpc; + return 1; + } else if ((finsn & 0xf00f) == 0xf002) { /* fmul */ + struct task_struct *tsk = current; + int fpscr; + int n, m, prec; + unsigned int hx, hy; + + n = (finsn >> 8) & 0xf; + m = (finsn >> 4) & 0xf; + hx = tsk->thread.fpu.hard.fp_regs[n]; + hy = tsk->thread.fpu.hard.fp_regs[m]; + fpscr = tsk->thread.fpu.hard.fpscr; + prec = fpscr & (1 << 19); + + if ((fpscr & FPSCR_FPU_ERROR) + && (prec && ((hx & 0x7fffffff) < 0x00100000 + || (hy & 0x7fffffff) < 0x00100000))) { + long long llx, lly; + + /* FPU error because of denormal */ + llx = ((long long) hx << 32) + | tsk->thread.fpu.hard.fp_regs[n+1]; + lly = ((long long) hy << 32) + | tsk->thread.fpu.hard.fp_regs[m+1]; + if ((hx & 0x7fffffff) >= 0x00100000) + llx = denormal_muld(lly, llx); + else + llx = denormal_muld(llx, lly); + tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; + tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; + } else if ((fpscr & FPSCR_FPU_ERROR) + && (!prec && ((hx & 0x7fffffff) < 0x00800000 + || (hy & 0x7fffffff) < 0x00800000))) { + /* FPU error because of denormal */ + if ((hx & 0x7fffffff) >= 0x00800000) + hx = denormal_mulf(hy, hx); + else + hx = denormal_mulf(hx, hy); + tsk->thread.fpu.hard.fp_regs[n] = hx; + } else + return 0; + + regs->pc = nextpc; + return 1; + } else if ((finsn & 0xf00e) == 0xf000) { /* fadd, fsub */ + struct task_struct *tsk = current; + int fpscr; + int n, m, prec; + unsigned int hx, hy; + + n = (finsn >> 8) & 0xf; + m = (finsn >> 4) & 0xf; + hx = tsk->thread.fpu.hard.fp_regs[n]; + hy = tsk->thread.fpu.hard.fp_regs[m]; + fpscr = tsk->thread.fpu.hard.fpscr; + prec = fpscr & (1 << 19); + + if ((fpscr & FPSCR_FPU_ERROR) + && (prec && ((hx & 0x7fffffff) < 0x00100000 + || (hy & 0x7fffffff) < 0x00100000))) { + long long llx, lly; + + /* FPU error because of denormal */ + llx = ((long long) hx << 32) + | tsk->thread.fpu.hard.fp_regs[n+1]; + lly = ((long long) hy << 32) + | tsk->thread.fpu.hard.fp_regs[m+1]; + if ((finsn & 0xf00f) == 0xf000) + llx = denormal_addd(llx, lly); + else + llx = denormal_addd(llx, lly ^ (1LL << 63)); + tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; + tsk->thread.fpu.hard.fp_regs[n+1] = llx & 0xffffffff; + } else if ((fpscr & FPSCR_FPU_ERROR) + && (!prec && ((hx & 0x7fffffff) < 0x00800000 + || (hy & 0x7fffffff) < 0x00800000))) { + /* FPU error because of denormal */ + if ((finsn & 0xf00f) == 0xf000) + hx = denormal_addf(hx, hy); + else + hx = denormal_addf(hx, hy ^ 0x80000000); + tsk->thread.fpu.hard.fp_regs[n] = hx; + } else + return 0; + + regs->pc = nextpc; + return 1; + } + + return 0; +} + +BUILD_TRAP_HANDLER(fpu_error) +{ + struct task_struct *tsk = current; + TRAP_HANDLER_DECL; + + save_fpu(tsk, regs); + if (ieee_fpe_handler(regs)) { + tsk->thread.fpu.hard.fpscr &= + ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); + grab_fpu(regs); + restore_fpu(tsk); + set_tsk_thread_flag(tsk, TIF_USEDFPU); + return; + } + + force_sig(SIGFPE, tsk); +} + +BUILD_TRAP_HANDLER(fpu_state_restore) +{ + struct task_struct *tsk = current; + TRAP_HANDLER_DECL; + + grab_fpu(regs); + if (!user_mode(regs)) { + printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); + return; + } + + if (used_math()) { + /* Using the FPU again. */ + restore_fpu(tsk); + } else { + /* First time FPU user. */ + fpu_init(); + set_used_math(); + } + set_tsk_thread_flag(tsk, TIF_USEDFPU); +} diff -puN arch/sh/kernel/cpu/sh2a/probe.c~git-sh arch/sh/kernel/cpu/sh2a/probe.c --- a/arch/sh/kernel/cpu/sh2a/probe.c~git-sh +++ a/arch/sh/kernel/cpu/sh2a/probe.c @@ -3,25 +3,36 @@ * * CPU Subtype Probing for SH-2A. * - * Copyright (C) 2004, 2005 Paul Mundt + * Copyright (C) 2004 - 2007 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. */ - #include #include #include int __init detect_cpu_and_cache_system(void) { - /* Just SH7206 for now .. */ - boot_cpu_data.type = CPU_SH7206; + /* All SH-2A CPUs have support for 16 and 32-bit opcodes.. */ boot_cpu_data.flags |= CPU_HAS_OP32; +#if defined(CONFIG_CPU_SUBTYPE_SH7203) + boot_cpu_data.type = CPU_SH7203; + /* SH7203 has an FPU.. */ + boot_cpu_data.flags |= CPU_HAS_FPU; +#elif defined(CONFIG_CPU_SUBTYPE_SH7263) + boot_cpu_data.type = CPU_SH7263; + boot_cpu_data.flags |= CPU_HAS_FPU; +#elif defined(CONFIG_CPU_SUBTYPE_SH7206) + boot_cpu_data.type = CPU_SH7206; + /* While SH7206 has a DSP.. */ + boot_cpu_data.flags |= CPU_HAS_DSP; +#endif + boot_cpu_data.dcache.ways = 4; - boot_cpu_data.dcache.way_incr = (1 << 11); + boot_cpu_data.dcache.way_incr = (1 << 11); boot_cpu_data.dcache.sets = 128; boot_cpu_data.dcache.entry_shift = 4; boot_cpu_data.dcache.linesz = L1_CACHE_BYTES; @@ -37,4 +48,3 @@ int __init detect_cpu_and_cache_system(v return 0; } - diff -puN /dev/null arch/sh/kernel/cpu/sh2a/setup-sh7203.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh2a/setup-sh7203.c @@ -0,0 +1,319 @@ +/* + * SH7203 and SH7263 Setup + * + * Copyright (C) 2007 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include + +enum { + UNUSED = 0, + + /* interrupt sources */ + IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7, + PINT0, PINT1, PINT2, PINT3, PINT4, PINT5, PINT6, PINT7, + DMAC0_DEI, DMAC0_HEI, DMAC1_DEI, DMAC1_HEI, + DMAC2_DEI, DMAC2_HEI, DMAC3_DEI, DMAC3_HEI, + DMAC4_DEI, DMAC4_HEI, DMAC5_DEI, DMAC5_HEI, + DMAC6_DEI, DMAC6_HEI, DMAC7_DEI, DMAC7_HEI, + USB, LCDC, CMT0, CMT1, BSC, WDT, + MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D, + MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F, + MTU2_TGI1A, MTU2_TGI1B, MTU2_TCI1V, MTU2_TCI1U, + MTU2_TGI2A, MTU2_TGI2B, MTU2_TCI2V, MTU2_TCI2U, + MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D, MTU2_TCI3V, + MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D, MTU2_TCI4V, + ADC_ADI, + IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, IIC30_TEI, + IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, IIC31_TEI, + IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, IIC32_TEI, + IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI, IIC33_TEI, + SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI, + SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI, + SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI, + SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI, + SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI, + SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI, + SSI0_SSII, SSI1_SSII, SSI2_SSII, SSI3_SSII, + + /* ROM-DEC, SDHI, SRC, and IEB are SH7263 specific */ + ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG, ROMDEC_ISEC, ROMDEC_IBUF, + ROMDEC_IREADY, + + FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, + + SDHI3, SDHI0, SDHI1, + + RTC_ARM, RTC_PRD, RTC_CUP, + RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, RCAN0_SLE, + RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, RCAN1_SLE, + + SRC_OVF, SRC_ODFI, SRC_IDEI, IEBI, + + /* interrupt groups */ + PINT, DMAC0, DMAC1, DMAC2, DMAC3, DMAC4, DMAC5, DMAC6, DMAC7, + MTU0_ABCD, MTU0_VEF, MTU1_AB, MTU1_VU, MTU2_AB, MTU2_VU, + MTU3_ABCD, MTU4_ABCD, + IIC30, IIC31, IIC32, IIC33, SCIF0, SCIF1, SCIF2, SCIF3, + SSU0, SSU1, ROMDEC, SDHI, FLCTL, RTC, RCAN0, RCAN1, SRC +}; + +static struct intc_vect vectors[] __initdata = { + INTC_IRQ(IRQ0, 64), INTC_IRQ(IRQ1, 65), + INTC_IRQ(IRQ2, 66), INTC_IRQ(IRQ3, 67), + INTC_IRQ(IRQ4, 68), INTC_IRQ(IRQ5, 69), + INTC_IRQ(IRQ6, 70), INTC_IRQ(IRQ7, 71), + INTC_IRQ(PINT0, 80), INTC_IRQ(PINT1, 81), + INTC_IRQ(PINT2, 82), INTC_IRQ(PINT3, 83), + INTC_IRQ(PINT4, 84), INTC_IRQ(PINT5, 85), + INTC_IRQ(PINT6, 86), INTC_IRQ(PINT7, 87), + INTC_IRQ(DMAC0_DEI, 108), INTC_IRQ(DMAC0_HEI, 109), + INTC_IRQ(DMAC1_DEI, 112), INTC_IRQ(DMAC1_HEI, 113), + INTC_IRQ(DMAC2_DEI, 116), INTC_IRQ(DMAC2_HEI, 117), + INTC_IRQ(DMAC3_DEI, 120), INTC_IRQ(DMAC3_HEI, 121), + INTC_IRQ(DMAC4_DEI, 124), INTC_IRQ(DMAC4_HEI, 125), + INTC_IRQ(DMAC5_DEI, 128), INTC_IRQ(DMAC5_HEI, 129), + INTC_IRQ(DMAC6_DEI, 132), INTC_IRQ(DMAC6_HEI, 133), + INTC_IRQ(DMAC7_DEI, 136), INTC_IRQ(DMAC7_HEI, 137), + INTC_IRQ(USB, 140), INTC_IRQ(LCDC, 141), + INTC_IRQ(CMT0, 142), INTC_IRQ(CMT1, 143), + INTC_IRQ(BSC, 144), INTC_IRQ(WDT, 145), + INTC_IRQ(MTU2_TGI0A, 146), INTC_IRQ(MTU2_TGI0B, 147), + INTC_IRQ(MTU2_TGI0C, 148), INTC_IRQ(MTU2_TGI0D, 149), + INTC_IRQ(MTU2_TCI0V, 150), + INTC_IRQ(MTU2_TGI0E, 151), INTC_IRQ(MTU2_TGI0F, 152), + INTC_IRQ(MTU2_TGI1A, 153), INTC_IRQ(MTU2_TGI1B, 154), + INTC_IRQ(MTU2_TCI1V, 155), INTC_IRQ(MTU2_TCI1U, 156), + INTC_IRQ(MTU2_TGI2A, 157), INTC_IRQ(MTU2_TGI2B, 158), + INTC_IRQ(MTU2_TCI2V, 159), INTC_IRQ(MTU2_TCI2U, 160), + INTC_IRQ(MTU2_TGI3A, 161), INTC_IRQ(MTU2_TGI3B, 162), + INTC_IRQ(MTU2_TGI3C, 163), INTC_IRQ(MTU2_TGI3D, 164), + INTC_IRQ(MTU2_TCI3V, 165), + INTC_IRQ(MTU2_TGI4A, 166), INTC_IRQ(MTU2_TGI4B, 167), + INTC_IRQ(MTU2_TGI4C, 168), INTC_IRQ(MTU2_TGI4D, 169), + INTC_IRQ(MTU2_TCI4V, 170), + INTC_IRQ(ADC_ADI, 171), + INTC_IRQ(IIC30_STPI, 172), INTC_IRQ(IIC30_NAKI, 173), + INTC_IRQ(IIC30_RXI, 174), INTC_IRQ(IIC30_TXI, 175), + INTC_IRQ(IIC30_TEI, 176), + INTC_IRQ(IIC31_STPI, 177), INTC_IRQ(IIC31_NAKI, 178), + INTC_IRQ(IIC31_RXI, 179), INTC_IRQ(IIC31_TXI, 180), + INTC_IRQ(IIC31_TEI, 181), + INTC_IRQ(IIC32_STPI, 182), INTC_IRQ(IIC32_NAKI, 183), + INTC_IRQ(IIC32_RXI, 184), INTC_IRQ(IIC32_TXI, 185), + INTC_IRQ(IIC32_TEI, 186), + INTC_IRQ(IIC33_STPI, 187), INTC_IRQ(IIC33_NAKI, 188), + INTC_IRQ(IIC33_RXI, 189), INTC_IRQ(IIC33_TXI, 190), + INTC_IRQ(IIC33_TEI, 191), + INTC_IRQ(SCIF0_BRI, 192), INTC_IRQ(SCIF0_ERI, 193), + INTC_IRQ(SCIF0_RXI, 194), INTC_IRQ(SCIF0_TXI, 195), + INTC_IRQ(SCIF1_BRI, 196), INTC_IRQ(SCIF1_ERI, 197), + INTC_IRQ(SCIF1_RXI, 198), INTC_IRQ(SCIF1_TXI, 199), + INTC_IRQ(SCIF2_BRI, 200), INTC_IRQ(SCIF2_ERI, 201), + INTC_IRQ(SCIF2_RXI, 202), INTC_IRQ(SCIF2_TXI, 203), + INTC_IRQ(SCIF3_BRI, 204), INTC_IRQ(SCIF3_ERI, 205), + INTC_IRQ(SCIF3_RXI, 206), INTC_IRQ(SCIF3_TXI, 207), + INTC_IRQ(SSU0_SSERI, 208), INTC_IRQ(SSU0_SSRXI, 209), + INTC_IRQ(SSU0_SSTXI, 210), + INTC_IRQ(SSU1_SSERI, 211), INTC_IRQ(SSU1_SSRXI, 212), + INTC_IRQ(SSU1_SSTXI, 213), + INTC_IRQ(SSI0_SSII, 214), INTC_IRQ(SSI1_SSII, 215), + INTC_IRQ(SSI2_SSII, 216), INTC_IRQ(SSI3_SSII, 217), + INTC_IRQ(FLCTL_FLSTEI, 224), INTC_IRQ(FLCTL_FLTENDI, 225), + INTC_IRQ(FLCTL_FLTREQ0I, 226), INTC_IRQ(FLCTL_FLTREQ1I, 227), + INTC_IRQ(RTC_ARM, 231), INTC_IRQ(RTC_PRD, 232), + INTC_IRQ(RTC_CUP, 233), + INTC_IRQ(RCAN0_ERS, 234), INTC_IRQ(RCAN0_OVR, 235), + INTC_IRQ(RCAN0_RM0, 236), INTC_IRQ(RCAN0_RM1, 237), + INTC_IRQ(RCAN0_SLE, 238), + INTC_IRQ(RCAN1_ERS, 239), INTC_IRQ(RCAN1_OVR, 240), + INTC_IRQ(RCAN1_RM0, 241), INTC_IRQ(RCAN1_RM1, 242), + INTC_IRQ(RCAN1_SLE, 243), + + /* SH7263-specific trash */ +#ifdef CONFIG_CPU_SUBTYPE_SH7263 + INTC_IRQ(ROMDEC_ISY, 218), INTC_IRQ(ROMDEC_IERR, 219), + INTC_IRQ(ROMDEC_IARG, 220), INTC_IRQ(ROMDEC_ISEC, 221), + INTC_IRQ(ROMDEC_IBUF, 222), INTC_IRQ(ROMDEC_IREADY, 223), + + INTC_IRQ(SDHI3, 228), INTC_IRQ(SDHI0, 229), INTC_IRQ(SDHI1, 230), + + INTC_IRQ(SRC_OVF, 244), INTC_IRQ(SRC_ODFI, 245), + INTC_IRQ(SRC_IDEI, 246), + + INTC_IRQ(IEBI, 247), +#endif +}; + +static struct intc_group groups[] __initdata = { + INTC_GROUP(PINT, PINT0, PINT1, PINT2, PINT3, + PINT4, PINT5, PINT6, PINT7), + INTC_GROUP(DMAC0, DMAC0_DEI, DMAC0_HEI), + INTC_GROUP(DMAC1, DMAC1_DEI, DMAC1_HEI), + INTC_GROUP(DMAC2, DMAC2_DEI, DMAC2_HEI), + INTC_GROUP(DMAC3, DMAC3_DEI, DMAC3_HEI), + INTC_GROUP(DMAC4, DMAC4_DEI, DMAC4_HEI), + INTC_GROUP(DMAC5, DMAC5_DEI, DMAC5_HEI), + INTC_GROUP(DMAC6, DMAC6_DEI, DMAC6_HEI), + INTC_GROUP(DMAC7, DMAC7_DEI, DMAC7_HEI), + INTC_GROUP(MTU0_ABCD, MTU2_TGI0A, MTU2_TGI0B, MTU2_TGI0C, MTU2_TGI0D), + INTC_GROUP(MTU0_VEF, MTU2_TCI0V, MTU2_TGI0E, MTU2_TGI0F), + INTC_GROUP(MTU1_AB, MTU2_TGI1A, MTU2_TGI1B), + INTC_GROUP(MTU1_VU, MTU2_TCI1V, MTU2_TCI1U), + INTC_GROUP(MTU2_AB, MTU2_TGI2A, MTU2_TGI2B), + INTC_GROUP(MTU2_VU, MTU2_TCI2V, MTU2_TCI2U), + INTC_GROUP(MTU3_ABCD, MTU2_TGI3A, MTU2_TGI3B, MTU2_TGI3C, MTU2_TGI3D), + INTC_GROUP(MTU4_ABCD, MTU2_TGI4A, MTU2_TGI4B, MTU2_TGI4C, MTU2_TGI4D), + INTC_GROUP(IIC30, IIC30_STPI, IIC30_NAKI, IIC30_RXI, IIC30_TXI, + IIC30_TEI), + INTC_GROUP(IIC31, IIC31_STPI, IIC31_NAKI, IIC31_RXI, IIC31_TXI, + IIC31_TEI), + INTC_GROUP(IIC32, IIC32_STPI, IIC32_NAKI, IIC32_RXI, IIC32_TXI, + IIC32_TEI), + INTC_GROUP(IIC33, IIC33_STPI, IIC33_NAKI, IIC33_RXI, IIC33_TXI, + IIC33_TEI), + INTC_GROUP(SCIF0, SCIF0_BRI, SCIF0_ERI, SCIF0_RXI, SCIF0_TXI), + INTC_GROUP(SCIF1, SCIF1_BRI, SCIF1_ERI, SCIF1_RXI, SCIF1_TXI), + INTC_GROUP(SCIF2, SCIF2_BRI, SCIF2_ERI, SCIF2_RXI, SCIF2_TXI), + INTC_GROUP(SCIF3, SCIF3_BRI, SCIF3_ERI, SCIF3_RXI, SCIF3_TXI), + INTC_GROUP(SSU0, SSU0_SSERI, SSU0_SSRXI, SSU0_SSTXI), + INTC_GROUP(SSU1, SSU1_SSERI, SSU1_SSRXI, SSU1_SSTXI), + INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, + FLCTL_FLTREQ1I), + INTC_GROUP(RTC, RTC_ARM, RTC_PRD, RTC_CUP), + INTC_GROUP(RCAN0, RCAN0_ERS, RCAN0_OVR, RCAN0_RM0, RCAN0_RM1, + RCAN0_SLE), + INTC_GROUP(RCAN1, RCAN1_ERS, RCAN1_OVR, RCAN1_RM0, RCAN1_RM1, + RCAN1_SLE), + +#ifdef CONFIG_CPU_SUBTYPE_SH7263 + INTC_GROUP(ROMDEC, ROMDEC_ISY, ROMDEC_IERR, ROMDEC_IARG, + ROMDEC_ISEC, ROMDEC_IBUF, ROMDEC_IREADY), + INTC_GROUP(SDHI, SDHI3, SDHI0, SDHI1), + INTC_GROUP(SRC, SRC_OVF, SRC_ODFI, SRC_IDEI), +#endif +}; + +static struct intc_prio_reg prio_registers[] __initdata = { + { 0xfffe0818, 0, 16, 4, /* IPR01 */ { IRQ0, IRQ1, IRQ2, IRQ3 } }, + { 0xfffe081a, 0, 16, 4, /* IPR02 */ { IRQ4, IRQ5, IRQ6, IRQ7 } }, + { 0xfffe0820, 0, 16, 4, /* IPR05 */ { PINT, 0, 0, 0 } }, + { 0xfffe0c00, 0, 16, 4, /* IPR06 */ { DMAC0, DMAC1, DMAC2, DMAC3 } }, + { 0xfffe0c02, 0, 16, 4, /* IPR07 */ { DMAC4, DMAC5, DMAC6, DMAC7 } }, + { 0xfffe0c04, 0, 16, 4, /* IPR08 */ { USB, LCDC, CMT0, CMT1 } }, + { 0xfffe0c06, 0, 16, 4, /* IPR09 */ { BSC, WDT, MTU0_ABCD, MTU0_VEF } }, + { 0xfffe0c08, 0, 16, 4, /* IPR10 */ { MTU1_AB, MTU1_VU, MTU2_AB, + MTU2_VU } }, + { 0xfffe0c0a, 0, 16, 4, /* IPR11 */ { MTU3_ABCD, MTU2_TCI3V, MTU4_ABCD, + MTU2_TCI4V } }, + { 0xfffe0c0c, 0, 16, 4, /* IPR12 */ { ADC_ADI, IIC30, IIC31, IIC32 } }, + { 0xfffe0c0e, 0, 16, 4, /* IPR13 */ { IIC33, SCIF0, SCIF1, SCIF2 } }, + { 0xfffe0c10, 0, 16, 4, /* IPR14 */ { SCIF3, SSU0, SSU1, SSI0_SSII } }, +#ifdef CONFIG_CPU_SUBTYPE_SH7203 + { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { SSI1_SSII, SSI2_SSII, + SSI3_SSII, 0 } }, + { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { FLCTL, 0, RTC, RCAN0 } }, + { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { RCAN1, 0, 0, 0 } }, +#else + { 0xfffe0c12, 0, 16, 4, /* IPR15 */ { SSI1_SSII, SSI2_SSII, + SSI3_SSII, ROMDEC } }, + { 0xfffe0c14, 0, 16, 4, /* IPR16 */ { FLCTL, SDHI, RTC, RCAN0 } }, + { 0xfffe0c16, 0, 16, 4, /* IPR17 */ { RCAN1, SRC, IEBI, 0 } }, +#endif +}; + +static struct intc_mask_reg mask_registers[] __initdata = { + { 0xfffe0808, 0, 16, /* PINTER */ + { 0, 0, 0, 0, 0, 0, 0, 0, + PINT7, PINT6, PINT5, PINT4, PINT3, PINT2, PINT1, PINT0 } }, +}; + +static DECLARE_INTC_DESC(intc_desc, "sh7203", vectors, groups, + NULL, mask_registers, prio_registers, NULL); + +static struct plat_sci_port sci_platform_data[] = { + { + .mapbase = 0xfffe8000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 193, 194, 195, 192 }, + }, { + .mapbase = 0xfffe8800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 197, 198, 199, 196 }, + }, { + .mapbase = 0xfffe9000, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 201, 202, 203, 200 }, + }, { + .mapbase = 0xfffe9800, + .flags = UPF_BOOT_AUTOCONF, + .type = PORT_SCIF, + .irqs = { 205, 206, 207, 204 }, + }, { + .flags = 0, + } +}; + +static struct platform_device sci_device = { + .name = "sh-sci", + .id = -1, + .dev = { + .platform_data = sci_platform_data, + }, +}; + +static struct resource rtc_resources[] = { + [0] = { + .start = 0xffff2000, + .end = 0xffff2000 + 0x58 - 1, + .flags = IORESOURCE_IO, + }, + [1] = { + /* Period IRQ */ + .start = 232, + .flags = IORESOURCE_IRQ, + }, + [2] = { + /* Carry IRQ */ + .start = 233, + .flags = IORESOURCE_IRQ, + }, + [3] = { + /* Alarm IRQ */ + .start = 231, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rtc_device = { + .name = "sh-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; + +static struct platform_device *sh7203_devices[] __initdata = { + &sci_device, + &rtc_device, +}; + +static int __init sh7203_devices_setup(void) +{ + return platform_add_devices(sh7203_devices, + ARRAY_SIZE(sh7203_devices)); +} +__initcall(sh7203_devices_setup); + +void __init plat_irq_setup(void) +{ + register_intc_controller(&intc_desc); +} diff -puN arch/sh/kernel/cpu/sh3/entry.S~git-sh arch/sh/kernel/cpu/sh3/entry.S --- a/arch/sh/kernel/cpu/sh3/entry.S~git-sh +++ a/arch/sh/kernel/cpu/sh3/entry.S @@ -13,8 +13,9 @@ #include #include #include -#include #include +#include +#include ! NOTE: ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address @@ -409,6 +410,27 @@ ENTRY(handle_exception) ! Using k0, k1 for scratch registers (r0_bank1, r1_bank), ! save all registers onto stack. ! + +#ifdef CONFIG_GUSA + ! Check for roll back gRB (User and Kernel) + mov r15, k0 + shll k0 + bf/s 1f + shll k0 + bf/s 1f + stc spc, k1 + stc r0_bank, k0 + cmp/hs k0, k1 ! test k1 (saved PC) >= k0 (saved r0) + bt/s 2f + stc r1_bank, k1 + + add #-2, k0 + add r15, k0 + ldc k0, spc ! PC = saved r0 + r15 - 2 +2: mov k1, r15 ! SP = r1 +1: +#endif + stc ssr, k0 ! Is it from kernel space? shll k0 ! Check MD bit (bit30) by shifting it into... shll k0 ! ...the T bit diff -puN arch/sh/kernel/cpu/sh3/ex.S~git-sh arch/sh/kernel/cpu/sh3/ex.S --- a/arch/sh/kernel/cpu/sh3/ex.S~git-sh +++ a/arch/sh/kernel/cpu/sh3/ex.S @@ -36,7 +36,7 @@ ENTRY(exception_handling_table) .long exception_error ! address error store /* 100 */ #endif #if defined(CONFIG_SH_FPU) - .long do_fpu_error /* 120 */ + .long fpu_error_trap_handler /* 120 */ #else .long exception_error /* 120 */ #endif diff -puN arch/sh/kernel/cpu/sh3/probe.c~git-sh arch/sh/kernel/cpu/sh3/probe.c --- a/arch/sh/kernel/cpu/sh3/probe.c~git-sh +++ a/arch/sh/kernel/cpu/sh3/probe.c @@ -16,11 +16,11 @@ #include #include -int __init detect_cpu_and_cache_system(void) +int __uses_jump_to_uncached detect_cpu_and_cache_system(void) { unsigned long addr0, addr1, data0, data1, data2, data3; - jump_to_P2(); + jump_to_uncached(); /* * Check if the entry shadows or not. * When shadowed, it's 128-entry system. @@ -48,7 +48,7 @@ int __init detect_cpu_and_cache_system(v ctrl_outl(data0&~SH_CACHE_VALID, addr0); ctrl_outl(data2&~SH_CACHE_VALID, addr1); - back_to_P1(); + back_to_cached(); boot_cpu_data.dcache.ways = 4; boot_cpu_data.dcache.entry_shift = 4; diff -puN arch/sh/kernel/cpu/sh4/Makefile~git-sh arch/sh/kernel/cpu/sh4/Makefile --- a/arch/sh/kernel/cpu/sh4/Makefile~git-sh +++ a/arch/sh/kernel/cpu/sh4/Makefile @@ -5,7 +5,7 @@ obj-y := probe.o common.o common-y += $(addprefix ../sh3/, entry.o ex.o) -obj-$(CONFIG_SH_FPU) += fpu.o +obj-$(CONFIG_SH_FPU) += fpu.o softfloat.o obj-$(CONFIG_SH_STORE_QUEUES) += sq.o # CPU subtype setup diff -puN arch/sh/kernel/cpu/sh4/fpu.c~git-sh arch/sh/kernel/cpu/sh4/fpu.c --- a/arch/sh/kernel/cpu/sh4/fpu.c~git-sh +++ a/arch/sh/kernel/cpu/sh4/fpu.c @@ -1,7 +1,4 @@ -/* $Id: fpu.c,v 1.4 2004/01/13 05:52:11 kkojima Exp $ - * - * linux/arch/sh/kernel/fpu.c - * +/* * Save/restore floating point context for signal handlers. * * This file is subject to the terms and conditions of the GNU General Public @@ -9,15 +6,16 @@ * for more details. * * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * Copyright (C) 2006 ST Microelectronics Ltd. (denorm support) * - * FIXME! These routines can be optimized in big endian case. + * FIXME! These routines have not been tested for big endian case. */ - #include #include +#include +#include #include #include -#include /* The PR (precision) bit in the FP Status Register must be clear when * an frchg instruction is executed, otherwise the instruction is undefined. @@ -25,177 +23,184 @@ */ #define FPSCR_RCHG 0x00000000 +extern unsigned long long float64_div(unsigned long long a, + unsigned long long b); +extern unsigned long int float32_div(unsigned long int a, unsigned long int b); +extern unsigned long long float64_mul(unsigned long long a, + unsigned long long b); +extern unsigned long int float32_mul(unsigned long int a, unsigned long int b); +extern unsigned long long float64_add(unsigned long long a, + unsigned long long b); +extern unsigned long int float32_add(unsigned long int a, unsigned long int b); +extern unsigned long long float64_sub(unsigned long long a, + unsigned long long b); +extern unsigned long int float32_sub(unsigned long int a, unsigned long int b); +static unsigned int fpu_exception_flags; /* * Save FPU registers onto task structure. * Assume called with FPU enabled (SR.FD=0). */ -void -save_fpu(struct task_struct *tsk, struct pt_regs *regs) +void save_fpu(struct task_struct *tsk, struct pt_regs *regs) { unsigned long dummy; clear_tsk_thread_flag(tsk, TIF_USEDFPU); enable_fpu(); - asm volatile("sts.l fpul, @-%0\n\t" - "sts.l fpscr, @-%0\n\t" - "lds %2, fpscr\n\t" - "frchg\n\t" - "fmov.s fr15, @-%0\n\t" - "fmov.s fr14, @-%0\n\t" - "fmov.s fr13, @-%0\n\t" - "fmov.s fr12, @-%0\n\t" - "fmov.s fr11, @-%0\n\t" - "fmov.s fr10, @-%0\n\t" - "fmov.s fr9, @-%0\n\t" - "fmov.s fr8, @-%0\n\t" - "fmov.s fr7, @-%0\n\t" - "fmov.s fr6, @-%0\n\t" - "fmov.s fr5, @-%0\n\t" - "fmov.s fr4, @-%0\n\t" - "fmov.s fr3, @-%0\n\t" - "fmov.s fr2, @-%0\n\t" - "fmov.s fr1, @-%0\n\t" - "fmov.s fr0, @-%0\n\t" - "frchg\n\t" - "fmov.s fr15, @-%0\n\t" - "fmov.s fr14, @-%0\n\t" - "fmov.s fr13, @-%0\n\t" - "fmov.s fr12, @-%0\n\t" - "fmov.s fr11, @-%0\n\t" - "fmov.s fr10, @-%0\n\t" - "fmov.s fr9, @-%0\n\t" - "fmov.s fr8, @-%0\n\t" - "fmov.s fr7, @-%0\n\t" - "fmov.s fr6, @-%0\n\t" - "fmov.s fr5, @-%0\n\t" - "fmov.s fr4, @-%0\n\t" - "fmov.s fr3, @-%0\n\t" - "fmov.s fr2, @-%0\n\t" - "fmov.s fr1, @-%0\n\t" - "fmov.s fr0, @-%0\n\t" - "lds %3, fpscr\n\t" - : "=r" (dummy) - : "0" ((char *)(&tsk->thread.fpu.hard.status)), - "r" (FPSCR_RCHG), - "r" (FPSCR_INIT) - : "memory"); + asm volatile ("sts.l fpul, @-%0\n\t" + "sts.l fpscr, @-%0\n\t" + "lds %2, fpscr\n\t" + "frchg\n\t" + "fmov.s fr15, @-%0\n\t" + "fmov.s fr14, @-%0\n\t" + "fmov.s fr13, @-%0\n\t" + "fmov.s fr12, @-%0\n\t" + "fmov.s fr11, @-%0\n\t" + "fmov.s fr10, @-%0\n\t" + "fmov.s fr9, @-%0\n\t" + "fmov.s fr8, @-%0\n\t" + "fmov.s fr7, @-%0\n\t" + "fmov.s fr6, @-%0\n\t" + "fmov.s fr5, @-%0\n\t" + "fmov.s fr4, @-%0\n\t" + "fmov.s fr3, @-%0\n\t" + "fmov.s fr2, @-%0\n\t" + "fmov.s fr1, @-%0\n\t" + "fmov.s fr0, @-%0\n\t" + "frchg\n\t" + "fmov.s fr15, @-%0\n\t" + "fmov.s fr14, @-%0\n\t" + "fmov.s fr13, @-%0\n\t" + "fmov.s fr12, @-%0\n\t" + "fmov.s fr11, @-%0\n\t" + "fmov.s fr10, @-%0\n\t" + "fmov.s fr9, @-%0\n\t" + "fmov.s fr8, @-%0\n\t" + "fmov.s fr7, @-%0\n\t" + "fmov.s fr6, @-%0\n\t" + "fmov.s fr5, @-%0\n\t" + "fmov.s fr4, @-%0\n\t" + "fmov.s fr3, @-%0\n\t" + "fmov.s fr2, @-%0\n\t" + "fmov.s fr1, @-%0\n\t" + "fmov.s fr0, @-%0\n\t" + "lds %3, fpscr\n\t":"=r" (dummy) + :"0"((char *)(&tsk->thread.fpu.hard.status)), + "r"(FPSCR_RCHG), "r"(FPSCR_INIT) + :"memory"); - disable_fpu(); - release_fpu(regs); + disable_fpu(); + release_fpu(regs); } -static void -restore_fpu(struct task_struct *tsk) +static void restore_fpu(struct task_struct *tsk) { unsigned long dummy; - enable_fpu(); - asm volatile("lds %2, fpscr\n\t" - "fmov.s @%0+, fr0\n\t" - "fmov.s @%0+, fr1\n\t" - "fmov.s @%0+, fr2\n\t" - "fmov.s @%0+, fr3\n\t" - "fmov.s @%0+, fr4\n\t" - "fmov.s @%0+, fr5\n\t" - "fmov.s @%0+, fr6\n\t" - "fmov.s @%0+, fr7\n\t" - "fmov.s @%0+, fr8\n\t" - "fmov.s @%0+, fr9\n\t" - "fmov.s @%0+, fr10\n\t" - "fmov.s @%0+, fr11\n\t" - "fmov.s @%0+, fr12\n\t" - "fmov.s @%0+, fr13\n\t" - "fmov.s @%0+, fr14\n\t" - "fmov.s @%0+, fr15\n\t" - "frchg\n\t" - "fmov.s @%0+, fr0\n\t" - "fmov.s @%0+, fr1\n\t" - "fmov.s @%0+, fr2\n\t" - "fmov.s @%0+, fr3\n\t" - "fmov.s @%0+, fr4\n\t" - "fmov.s @%0+, fr5\n\t" - "fmov.s @%0+, fr6\n\t" - "fmov.s @%0+, fr7\n\t" - "fmov.s @%0+, fr8\n\t" - "fmov.s @%0+, fr9\n\t" - "fmov.s @%0+, fr10\n\t" - "fmov.s @%0+, fr11\n\t" - "fmov.s @%0+, fr12\n\t" - "fmov.s @%0+, fr13\n\t" - "fmov.s @%0+, fr14\n\t" - "fmov.s @%0+, fr15\n\t" - "frchg\n\t" - "lds.l @%0+, fpscr\n\t" - "lds.l @%0+, fpul\n\t" - : "=r" (dummy) - : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG) - : "memory"); + enable_fpu(); + asm volatile ("lds %2, fpscr\n\t" + "fmov.s @%0+, fr0\n\t" + "fmov.s @%0+, fr1\n\t" + "fmov.s @%0+, fr2\n\t" + "fmov.s @%0+, fr3\n\t" + "fmov.s @%0+, fr4\n\t" + "fmov.s @%0+, fr5\n\t" + "fmov.s @%0+, fr6\n\t" + "fmov.s @%0+, fr7\n\t" + "fmov.s @%0+, fr8\n\t" + "fmov.s @%0+, fr9\n\t" + "fmov.s @%0+, fr10\n\t" + "fmov.s @%0+, fr11\n\t" + "fmov.s @%0+, fr12\n\t" + "fmov.s @%0+, fr13\n\t" + "fmov.s @%0+, fr14\n\t" + "fmov.s @%0+, fr15\n\t" + "frchg\n\t" + "fmov.s @%0+, fr0\n\t" + "fmov.s @%0+, fr1\n\t" + "fmov.s @%0+, fr2\n\t" + "fmov.s @%0+, fr3\n\t" + "fmov.s @%0+, fr4\n\t" + "fmov.s @%0+, fr5\n\t" + "fmov.s @%0+, fr6\n\t" + "fmov.s @%0+, fr7\n\t" + "fmov.s @%0+, fr8\n\t" + "fmov.s @%0+, fr9\n\t" + "fmov.s @%0+, fr10\n\t" + "fmov.s @%0+, fr11\n\t" + "fmov.s @%0+, fr12\n\t" + "fmov.s @%0+, fr13\n\t" + "fmov.s @%0+, fr14\n\t" + "fmov.s @%0+, fr15\n\t" + "frchg\n\t" + "lds.l @%0+, fpscr\n\t" + "lds.l @%0+, fpul\n\t" + :"=r" (dummy) + :"0"(&tsk->thread.fpu), "r"(FPSCR_RCHG) + :"memory"); disable_fpu(); } /* * Load the FPU with signalling NANS. This bit pattern we're using * has the property that no matter wether considered as single or as - * double precision represents signaling NANS. + * double precision represents signaling NANS. */ -static void -fpu_init(void) +static void fpu_init(void) { enable_fpu(); - asm volatile("lds %0, fpul\n\t" - "lds %1, fpscr\n\t" - "fsts fpul, fr0\n\t" - "fsts fpul, fr1\n\t" - "fsts fpul, fr2\n\t" - "fsts fpul, fr3\n\t" - "fsts fpul, fr4\n\t" - "fsts fpul, fr5\n\t" - "fsts fpul, fr6\n\t" - "fsts fpul, fr7\n\t" - "fsts fpul, fr8\n\t" - "fsts fpul, fr9\n\t" - "fsts fpul, fr10\n\t" - "fsts fpul, fr11\n\t" - "fsts fpul, fr12\n\t" - "fsts fpul, fr13\n\t" - "fsts fpul, fr14\n\t" - "fsts fpul, fr15\n\t" - "frchg\n\t" - "fsts fpul, fr0\n\t" - "fsts fpul, fr1\n\t" - "fsts fpul, fr2\n\t" - "fsts fpul, fr3\n\t" - "fsts fpul, fr4\n\t" - "fsts fpul, fr5\n\t" - "fsts fpul, fr6\n\t" - "fsts fpul, fr7\n\t" - "fsts fpul, fr8\n\t" - "fsts fpul, fr9\n\t" - "fsts fpul, fr10\n\t" - "fsts fpul, fr11\n\t" - "fsts fpul, fr12\n\t" - "fsts fpul, fr13\n\t" - "fsts fpul, fr14\n\t" - "fsts fpul, fr15\n\t" - "frchg\n\t" - "lds %2, fpscr\n\t" - : /* no output */ - : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); - disable_fpu(); + asm volatile ( "lds %0, fpul\n\t" + "lds %1, fpscr\n\t" + "fsts fpul, fr0\n\t" + "fsts fpul, fr1\n\t" + "fsts fpul, fr2\n\t" + "fsts fpul, fr3\n\t" + "fsts fpul, fr4\n\t" + "fsts fpul, fr5\n\t" + "fsts fpul, fr6\n\t" + "fsts fpul, fr7\n\t" + "fsts fpul, fr8\n\t" + "fsts fpul, fr9\n\t" + "fsts fpul, fr10\n\t" + "fsts fpul, fr11\n\t" + "fsts fpul, fr12\n\t" + "fsts fpul, fr13\n\t" + "fsts fpul, fr14\n\t" + "fsts fpul, fr15\n\t" + "frchg\n\t" + "fsts fpul, fr0\n\t" + "fsts fpul, fr1\n\t" + "fsts fpul, fr2\n\t" + "fsts fpul, fr3\n\t" + "fsts fpul, fr4\n\t" + "fsts fpul, fr5\n\t" + "fsts fpul, fr6\n\t" + "fsts fpul, fr7\n\t" + "fsts fpul, fr8\n\t" + "fsts fpul, fr9\n\t" + "fsts fpul, fr10\n\t" + "fsts fpul, fr11\n\t" + "fsts fpul, fr12\n\t" + "fsts fpul, fr13\n\t" + "fsts fpul, fr14\n\t" + "fsts fpul, fr15\n\t" + "frchg\n\t" + "lds %2, fpscr\n\t" + : /* no output */ + :"r" (0), "r"(FPSCR_RCHG), "r"(FPSCR_INIT)); + disable_fpu(); } /** - * denormal_to_double - Given denormalized float number, - * store double float + * denormal_to_double - Given denormalized float number, + * store double float * - * @fpu: Pointer to sh_fpu_hard structure - * @n: Index to FP register + * @fpu: Pointer to sh_fpu_hard structure + * @n: Index to FP register */ -static void -denormal_to_double (struct sh_fpu_hard_struct *fpu, int n) +static void denormal_to_double(struct sh_fpu_hard_struct *fpu, int n) { unsigned long du, dl; unsigned long x = fpu->fpul; @@ -212,7 +217,7 @@ denormal_to_double (struct sh_fpu_hard_s dl = x << 29; fpu->fp_regs[n] = du; - fpu->fp_regs[n+1] = dl; + fpu->fp_regs[n + 1] = dl; } } @@ -223,68 +228,191 @@ denormal_to_double (struct sh_fpu_hard_s * * Returns 1 when it's handled (should not cause exception). */ -static int -ieee_fpe_handler (struct pt_regs *regs) +static int ieee_fpe_handler(struct pt_regs *regs) { - unsigned short insn = *(unsigned short *) regs->pc; + unsigned short insn = *(unsigned short *)regs->pc; unsigned short finsn; unsigned long nextpc; int nib[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, - insn & 0xf}; + insn & 0xf + }; - if (nib[0] == 0xb || - (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) /* bsr & jsr */ - regs->pr = regs->pc + 4; - - if (nib[0] == 0xa || nib[0] == 0xb) { /* bra & bsr */ - nextpc = regs->pc + 4 + ((short) ((insn & 0xfff) << 4) >> 3); - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x8 && nib[1] == 0xd) { /* bt/s */ + if (nib[0] == 0xb || (nib[0] == 0x4 && nib[2] == 0x0 && nib[3] == 0xb)) + regs->pr = regs->pc + 4; /* bsr & jsr */ + + if (nib[0] == 0xa || nib[0] == 0xb) { + /* bra & bsr */ + nextpc = regs->pc + 4 + ((short)((insn & 0xfff) << 4) >> 3); + finsn = *(unsigned short *)(regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xd) { + /* bt/s */ if (regs->sr & 1) - nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); + nextpc = regs->pc + 4 + ((char)(insn & 0xff) << 1); else nextpc = regs->pc + 4; - finsn = *(unsigned short *) (regs->pc + 2); - } else if (nib[0] == 0x8 && nib[1] == 0xf) { /* bf/s */ + finsn = *(unsigned short *)(regs->pc + 2); + } else if (nib[0] == 0x8 && nib[1] == 0xf) { + /* bf/s */ if (regs->sr & 1) nextpc = regs->pc + 4; else - nextpc = regs->pc + 4 + ((char) (insn & 0xff) << 1); - finsn = *(unsigned short *) (regs->pc + 2); + nextpc = regs->pc + 4 + ((char)(insn & 0xff) << 1); + finsn = *(unsigned short *)(regs->pc + 2); } else if (nib[0] == 0x4 && nib[3] == 0xb && - (nib[2] == 0x0 || nib[2] == 0x2)) { /* jmp & jsr */ + (nib[2] == 0x0 || nib[2] == 0x2)) { + /* jmp & jsr */ nextpc = regs->regs[nib[1]]; - finsn = *(unsigned short *) (regs->pc + 2); + finsn = *(unsigned short *)(regs->pc + 2); } else if (nib[0] == 0x0 && nib[3] == 0x3 && - (nib[2] == 0x0 || nib[2] == 0x2)) { /* braf & bsrf */ + (nib[2] == 0x0 || nib[2] == 0x2)) { + /* braf & bsrf */ nextpc = regs->pc + 4 + regs->regs[nib[1]]; - finsn = *(unsigned short *) (regs->pc + 2); - } else if (insn == 0x000b) { /* rts */ + finsn = *(unsigned short *)(regs->pc + 2); + } else if (insn == 0x000b) { + /* rts */ nextpc = regs->pr; - finsn = *(unsigned short *) (regs->pc + 2); + finsn = *(unsigned short *)(regs->pc + 2); } else { nextpc = regs->pc + instruction_size(insn); finsn = insn; } - if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ + if ((finsn & 0xf1ff) == 0xf0ad) { + /* fcnvsd */ struct task_struct *tsk = current; save_fpu(tsk, regs); - if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) { + if ((tsk->thread.fpu.hard.fpscr & FPSCR_CAUSE_ERROR)) /* FPU error */ - denormal_to_double (&tsk->thread.fpu.hard, - (finsn >> 8) & 0xf); - tsk->thread.fpu.hard.fpscr &= - ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); - grab_fpu(regs); - restore_fpu(tsk); - set_tsk_thread_flag(tsk, TIF_USEDFPU); + denormal_to_double(&tsk->thread.fpu.hard, + (finsn >> 8) & 0xf); + else + return 0; + + regs->pc = nextpc; + return 1; + } else if ((finsn & 0xf00f) == 0xf002) { + /* fmul */ + struct task_struct *tsk = current; + int fpscr; + int n, m, prec; + unsigned int hx, hy; + + n = (finsn >> 8) & 0xf; + m = (finsn >> 4) & 0xf; + hx = tsk->thread.fpu.hard.fp_regs[n]; + hy = tsk->thread.fpu.hard.fp_regs[m]; + fpscr = tsk->thread.fpu.hard.fpscr; + prec = fpscr & FPSCR_DBL_PRECISION; + + if ((fpscr & FPSCR_CAUSE_ERROR) + && (prec && ((hx & 0x7fffffff) < 0x00100000 + || (hy & 0x7fffffff) < 0x00100000))) { + long long llx, lly; + + /* FPU error because of denormal (doubles) */ + llx = ((long long)hx << 32) + | tsk->thread.fpu.hard.fp_regs[n + 1]; + lly = ((long long)hy << 32) + | tsk->thread.fpu.hard.fp_regs[m + 1]; + llx = float64_mul(llx, lly); + tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; + tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; + } else if ((fpscr & FPSCR_CAUSE_ERROR) + && (!prec && ((hx & 0x7fffffff) < 0x00800000 + || (hy & 0x7fffffff) < 0x00800000))) { + /* FPU error because of denormal (floats) */ + hx = float32_mul(hx, hy); + tsk->thread.fpu.hard.fp_regs[n] = hx; + } else + return 0; + + regs->pc = nextpc; + return 1; + } else if ((finsn & 0xf00e) == 0xf000) { + /* fadd, fsub */ + struct task_struct *tsk = current; + int fpscr; + int n, m, prec; + unsigned int hx, hy; + + n = (finsn >> 8) & 0xf; + m = (finsn >> 4) & 0xf; + hx = tsk->thread.fpu.hard.fp_regs[n]; + hy = tsk->thread.fpu.hard.fp_regs[m]; + fpscr = tsk->thread.fpu.hard.fpscr; + prec = fpscr & FPSCR_DBL_PRECISION; + + if ((fpscr & FPSCR_CAUSE_ERROR) + && (prec && ((hx & 0x7fffffff) < 0x00100000 + || (hy & 0x7fffffff) < 0x00100000))) { + long long llx, lly; + + /* FPU error because of denormal (doubles) */ + llx = ((long long)hx << 32) + | tsk->thread.fpu.hard.fp_regs[n + 1]; + lly = ((long long)hy << 32) + | tsk->thread.fpu.hard.fp_regs[m + 1]; + if ((finsn & 0xf00f) == 0xf000) + llx = float64_add(llx, lly); + else + llx = float64_sub(llx, lly); + tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; + tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; + } else if ((fpscr & FPSCR_CAUSE_ERROR) + && (!prec && ((hx & 0x7fffffff) < 0x00800000 + || (hy & 0x7fffffff) < 0x00800000))) { + /* FPU error because of denormal (floats) */ + if ((finsn & 0xf00f) == 0xf000) + hx = float32_add(hx, hy); + else + hx = float32_sub(hx, hy); + tsk->thread.fpu.hard.fp_regs[n] = hx; } else - force_sig(SIGFPE, tsk); + return 0; + + regs->pc = nextpc; + return 1; + } else if ((finsn & 0xf003) == 0xf003) { + /* fdiv */ + struct task_struct *tsk = current; + int fpscr; + int n, m, prec; + unsigned int hx, hy; + + n = (finsn >> 8) & 0xf; + m = (finsn >> 4) & 0xf; + hx = tsk->thread.fpu.hard.fp_regs[n]; + hy = tsk->thread.fpu.hard.fp_regs[m]; + fpscr = tsk->thread.fpu.hard.fpscr; + prec = fpscr & FPSCR_DBL_PRECISION; + + if ((fpscr & FPSCR_CAUSE_ERROR) + && (prec && ((hx & 0x7fffffff) < 0x00100000 + || (hy & 0x7fffffff) < 0x00100000))) { + long long llx, lly; + + /* FPU error because of denormal (doubles) */ + llx = ((long long)hx << 32) + | tsk->thread.fpu.hard.fp_regs[n + 1]; + lly = ((long long)hy << 32) + | tsk->thread.fpu.hard.fp_regs[m + 1]; + + llx = float64_div(llx, lly); + + tsk->thread.fpu.hard.fp_regs[n] = llx >> 32; + tsk->thread.fpu.hard.fp_regs[n + 1] = llx & 0xffffffff; + } else if ((fpscr & FPSCR_CAUSE_ERROR) + && (!prec && ((hx & 0x7fffffff) < 0x00800000 + || (hy & 0x7fffffff) < 0x00800000))) { + /* FPU error because of denormal (floats) */ + hx = float32_div(hx, hy); + tsk->thread.fpu.hard.fp_regs[n] = hx; + } else + return 0; regs->pc = nextpc; return 1; @@ -293,27 +421,48 @@ ieee_fpe_handler (struct pt_regs *regs) return 0; } -asmlinkage void -do_fpu_error(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs __regs) +void float_raise(unsigned int flags) +{ + fpu_exception_flags |= flags; +} + +int float_rounding_mode(void) { - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; + int roundingMode = FPSCR_ROUNDING_MODE(tsk->thread.fpu.hard.fpscr); + return roundingMode; +} - if (ieee_fpe_handler(regs)) - return; +BUILD_TRAP_HANDLER(fpu_error) +{ + struct task_struct *tsk = current; + TRAP_HANDLER_DECL; - regs->pc += 2; save_fpu(tsk, regs); + fpu_exception_flags = 0; + if (ieee_fpe_handler(regs)) { + tsk->thread.fpu.hard.fpscr &= + ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); + tsk->thread.fpu.hard.fpscr |= fpu_exception_flags; + /* Set the FPSCR flag as well as cause bits - simply + * replicate the cause */ + tsk->thread.fpu.hard.fpscr |= (fpu_exception_flags >> 10); + grab_fpu(regs); + restore_fpu(tsk); + set_tsk_thread_flag(tsk, TIF_USEDFPU); + if ((((tsk->thread.fpu.hard.fpscr & FPSCR_ENABLE_MASK) >> 7) & + (fpu_exception_flags >> 2)) == 0) { + return; + } + } + force_sig(SIGFPE, tsk); } -asmlinkage void -do_fpu_state_restore(unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, struct pt_regs __regs) +BUILD_TRAP_HANDLER(fpu_state_restore) { - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); struct task_struct *tsk = current; + TRAP_HANDLER_DECL; grab_fpu(regs); if (!user_mode(regs)) { @@ -324,7 +473,7 @@ do_fpu_state_restore(unsigned long r4, u if (used_math()) { /* Using the FPU again. */ restore_fpu(tsk); - } else { + } else { /* First time FPU user. */ fpu_init(); set_used_math(); diff -puN /dev/null arch/sh/kernel/cpu/sh4/softfloat.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh4/softfloat.c @@ -0,0 +1,892 @@ +/* + * Floating point emulation support for subnormalised numbers on SH4 + * architecture This file is derived from the SoftFloat IEC/IEEE + * Floating-point Arithmetic Package, Release 2 the original license of + * which is reproduced below. + * + * ======================================================================== + * + * This C source file is part of the SoftFloat IEC/IEEE Floating-point + * Arithmetic Package, Release 2. + * + * Written by John R. Hauser. This work was made possible in part by the + * International Computer Science Institute, located at Suite 600, 1947 Center + * Street, Berkeley, California 94704. Funding was partially provided by the + * National Science Foundation under grant MIP-9311980. The original version + * of this code was written as part of a project to build a fixed-point vector + * processor in collaboration with the University of California at Berkeley, + * overseen by Profs. Nelson Morgan and John Wawrzynek. More information + * is available through the web page `http://HTTP.CS.Berkeley.EDU/~jhauser/ + * arithmetic/softfloat.html'. + * + * THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort + * has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT + * TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO + * PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY + * AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. + * + * Derivative works are acceptable, even for commercial purposes, so long as + * (1) they include prominent notice that the work is derivative, and (2) they + * include prominent notice akin to these three paragraphs for those parts of + * this code that are retained. + * + * ======================================================================== + * + * SH4 modifications by Ismail Dhaoui + * and Kamel Khelifi + */ +#include +#include + +#define LIT64( a ) a##LL + +typedef char flag; +typedef unsigned char uint8; +typedef signed char int8; +typedef int uint16; +typedef int int16; +typedef unsigned int uint32; +typedef signed int int32; + +typedef unsigned long long int bits64; +typedef signed long long int sbits64; + +typedef unsigned char bits8; +typedef signed char sbits8; +typedef unsigned short int bits16; +typedef signed short int sbits16; +typedef unsigned int bits32; +typedef signed int sbits32; + +typedef unsigned long long int uint64; +typedef signed long long int int64; + +typedef unsigned long int float32; +typedef unsigned long long float64; + +extern void float_raise(unsigned int flags); /* in fpu.c */ +extern int float_rounding_mode(void); /* in fpu.c */ + +inline bits64 extractFloat64Frac(float64 a); +inline flag extractFloat64Sign(float64 a); +inline int16 extractFloat64Exp(float64 a); +inline int16 extractFloat32Exp(float32 a); +inline flag extractFloat32Sign(float32 a); +inline bits32 extractFloat32Frac(float32 a); +inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig); +inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr); +inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig); +inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr); +float64 float64_sub(float64 a, float64 b); +float32 float32_sub(float32 a, float32 b); +float32 float32_add(float32 a, float32 b); +float64 float64_add(float64 a, float64 b); +float64 float64_div(float64 a, float64 b); +float32 float32_div(float32 a, float32 b); +float32 float32_mul(float32 a, float32 b); +float64 float64_mul(float64 a, float64 b); +inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, + bits64 * z1Ptr); +inline void sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, + bits64 * z1Ptr); +inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr); + +static int8 countLeadingZeros32(bits32 a); +static int8 countLeadingZeros64(bits64 a); +static float64 normalizeRoundAndPackFloat64(flag zSign, int16 zExp, + bits64 zSig); +static float64 subFloat64Sigs(float64 a, float64 b, flag zSign); +static float64 addFloat64Sigs(float64 a, float64 b, flag zSign); +static float32 roundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig); +static float32 normalizeRoundAndPackFloat32(flag zSign, int16 zExp, + bits32 zSig); +static float64 roundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig); +static float32 subFloat32Sigs(float32 a, float32 b, flag zSign); +static float32 addFloat32Sigs(float32 a, float32 b, flag zSign); +static void normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, + bits64 * zSigPtr); +static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b); +static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr, + bits32 * zSigPtr); + +inline bits64 extractFloat64Frac(float64 a) +{ + return a & LIT64(0x000FFFFFFFFFFFFF); +} + +inline flag extractFloat64Sign(float64 a) +{ + return a >> 63; +} + +inline int16 extractFloat64Exp(float64 a) +{ + return (a >> 52) & 0x7FF; +} + +inline int16 extractFloat32Exp(float32 a) +{ + return (a >> 23) & 0xFF; +} + +inline flag extractFloat32Sign(float32 a) +{ + return a >> 31; +} + +inline bits32 extractFloat32Frac(float32 a) +{ + return a & 0x007FFFFF; +} + +inline float64 packFloat64(flag zSign, int16 zExp, bits64 zSig) +{ + return (((bits64) zSign) << 63) + (((bits64) zExp) << 52) + zSig; +} + +inline void shift64RightJamming(bits64 a, int16 count, bits64 * zPtr) +{ + bits64 z; + + if (count == 0) { + z = a; + } else if (count < 64) { + z = (a >> count) | ((a << ((-count) & 63)) != 0); + } else { + z = (a != 0); + } + *zPtr = z; +} + +static int8 countLeadingZeros32(bits32 a) +{ + static const int8 countLeadingZerosHigh[] = { + 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + int8 shiftCount; + + shiftCount = 0; + if (a < 0x10000) { + shiftCount += 16; + a <<= 16; + } + if (a < 0x1000000) { + shiftCount += 8; + a <<= 8; + } + shiftCount += countLeadingZerosHigh[a >> 24]; + return shiftCount; + +} + +static int8 countLeadingZeros64(bits64 a) +{ + int8 shiftCount; + + shiftCount = 0; + if (a < ((bits64) 1) << 32) { + shiftCount += 32; + } else { + a >>= 32; + } + shiftCount += countLeadingZeros32(a); + return shiftCount; + +} + +static float64 normalizeRoundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64(zSig) - 1; + return roundAndPackFloat64(zSign, zExp - shiftCount, + zSig << shiftCount); + +} + +static float64 subFloat64Sigs(float64 a, float64 b, flag zSign) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + expDiff = aExp - bExp; + aSig <<= 10; + bSig <<= 10; + if (0 < expDiff) + goto aExpBigger; + if (expDiff < 0) + goto bExpBigger; + if (aExp == 0) { + aExp = 1; + bExp = 1; + } + if (bSig < aSig) + goto aBigger; + if (aSig < bSig) + goto bBigger; + return packFloat64(float_rounding_mode() == FPSCR_RM_ZERO, 0, 0); + bExpBigger: + if (bExp == 0x7FF) { + return packFloat64(zSign ^ 1, 0x7FF, 0); + } + if (aExp == 0) { + ++expDiff; + } else { + aSig |= LIT64(0x4000000000000000); + } + shift64RightJamming(aSig, -expDiff, &aSig); + bSig |= LIT64(0x4000000000000000); + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if (aExp == 0x7FF) { + return a; + } + if (bExp == 0) { + --expDiff; + } else { + bSig |= LIT64(0x4000000000000000); + } + shift64RightJamming(bSig, expDiff, &bSig); + aSig |= LIT64(0x4000000000000000); + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat64(zSign, zExp, zSig); + +} +static float64 addFloat64Sigs(float64 a, float64 b, flag zSign) +{ + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + expDiff = aExp - bExp; + aSig <<= 9; + bSig <<= 9; + if (0 < expDiff) { + if (aExp == 0x7FF) { + return a; + } + if (bExp == 0) { + --expDiff; + } else { + bSig |= LIT64(0x2000000000000000); + } + shift64RightJamming(bSig, expDiff, &bSig); + zExp = aExp; + } else if (expDiff < 0) { + if (bExp == 0x7FF) { + return packFloat64(zSign, 0x7FF, 0); + } + if (aExp == 0) { + ++expDiff; + } else { + aSig |= LIT64(0x2000000000000000); + } + shift64RightJamming(aSig, -expDiff, &aSig); + zExp = bExp; + } else { + if (aExp == 0x7FF) { + return a; + } + if (aExp == 0) + return packFloat64(zSign, 0, (aSig + bSig) >> 9); + zSig = LIT64(0x4000000000000000) + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= LIT64(0x2000000000000000); + zSig = (aSig + bSig) << 1; + --zExp; + if ((sbits64) zSig < 0) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat64(zSign, zExp, zSig); + +} + +inline float32 packFloat32(flag zSign, int16 zExp, bits32 zSig) +{ + return (((bits32) zSign) << 31) + (((bits32) zExp) << 23) + zSig; +} + +inline void shift32RightJamming(bits32 a, int16 count, bits32 * zPtr) +{ + bits32 z; + if (count == 0) { + z = a; + } else if (count < 32) { + z = (a >> count) | ((a << ((-count) & 31)) != 0); + } else { + z = (a != 0); + } + *zPtr = z; +} + +static float32 roundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig) +{ + flag roundNearestEven; + int8 roundIncrement, roundBits; + flag isTiny; + + /* SH4 has only 2 rounding modes - round to nearest and round to zero */ + roundNearestEven = (float_rounding_mode() == FPSCR_RM_NEAREST); + roundIncrement = 0x40; + if (!roundNearestEven) { + roundIncrement = 0; + } + roundBits = zSig & 0x7F; + if (0xFD <= (bits16) zExp) { + if ((0xFD < zExp) + || ((zExp == 0xFD) + && ((sbits32) (zSig + roundIncrement) < 0)) + ) { + float_raise(FPSCR_CAUSE_OVERFLOW | FPSCR_CAUSE_INEXACT); + return packFloat32(zSign, 0xFF, + 0) - (roundIncrement == 0); + } + if (zExp < 0) { + isTiny = (zExp < -1) + || (zSig + roundIncrement < 0x80000000); + shift32RightJamming(zSig, -zExp, &zSig); + zExp = 0; + roundBits = zSig & 0x7F; + if (isTiny && roundBits) + float_raise(FPSCR_CAUSE_UNDERFLOW); + } + } + if (roundBits) + float_raise(FPSCR_CAUSE_INEXACT); + zSig = (zSig + roundIncrement) >> 7; + zSig &= ~(((roundBits ^ 0x40) == 0) & roundNearestEven); + if (zSig == 0) + zExp = 0; + return packFloat32(zSign, zExp, zSig); + +} + +static float32 normalizeRoundAndPackFloat32(flag zSign, int16 zExp, bits32 zSig) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32(zSig) - 1; + return roundAndPackFloat32(zSign, zExp - shiftCount, + zSig << shiftCount); +} + +static float64 roundAndPackFloat64(flag zSign, int16 zExp, bits64 zSig) +{ + flag roundNearestEven; + int16 roundIncrement, roundBits; + flag isTiny; + + /* SH4 has only 2 rounding modes - round to nearest and round to zero */ + roundNearestEven = (float_rounding_mode() == FPSCR_RM_NEAREST); + roundIncrement = 0x200; + if (!roundNearestEven) { + roundIncrement = 0; + } + roundBits = zSig & 0x3FF; + if (0x7FD <= (bits16) zExp) { + if ((0x7FD < zExp) + || ((zExp == 0x7FD) + && ((sbits64) (zSig + roundIncrement) < 0)) + ) { + float_raise(FPSCR_CAUSE_OVERFLOW | FPSCR_CAUSE_INEXACT); + return packFloat64(zSign, 0x7FF, + 0) - (roundIncrement == 0); + } + if (zExp < 0) { + isTiny = (zExp < -1) + || (zSig + roundIncrement < + LIT64(0x8000000000000000)); + shift64RightJamming(zSig, -zExp, &zSig); + zExp = 0; + roundBits = zSig & 0x3FF; + if (isTiny && roundBits) + float_raise(FPSCR_CAUSE_UNDERFLOW); + } + } + if (roundBits) + float_raise(FPSCR_CAUSE_INEXACT); + zSig = (zSig + roundIncrement) >> 10; + zSig &= ~(((roundBits ^ 0x200) == 0) & roundNearestEven); + if (zSig == 0) + zExp = 0; + return packFloat64(zSign, zExp, zSig); + +} + +static float32 subFloat32Sigs(float32 a, float32 b, flag zSign) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + expDiff = aExp - bExp; + aSig <<= 7; + bSig <<= 7; + if (0 < expDiff) + goto aExpBigger; + if (expDiff < 0) + goto bExpBigger; + if (aExp == 0) { + aExp = 1; + bExp = 1; + } + if (bSig < aSig) + goto aBigger; + if (aSig < bSig) + goto bBigger; + return packFloat32(float_rounding_mode() == FPSCR_RM_ZERO, 0, 0); + bExpBigger: + if (bExp == 0xFF) { + return packFloat32(zSign ^ 1, 0xFF, 0); + } + if (aExp == 0) { + ++expDiff; + } else { + aSig |= 0x40000000; + } + shift32RightJamming(aSig, -expDiff, &aSig); + bSig |= 0x40000000; + bBigger: + zSig = bSig - aSig; + zExp = bExp; + zSign ^= 1; + goto normalizeRoundAndPack; + aExpBigger: + if (aExp == 0xFF) { + return a; + } + if (bExp == 0) { + --expDiff; + } else { + bSig |= 0x40000000; + } + shift32RightJamming(bSig, expDiff, &bSig); + aSig |= 0x40000000; + aBigger: + zSig = aSig - bSig; + zExp = aExp; + normalizeRoundAndPack: + --zExp; + return normalizeRoundAndPackFloat32(zSign, zExp, zSig); + +} + +static float32 addFloat32Sigs(float32 a, float32 b, flag zSign) +{ + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + int16 expDiff; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + expDiff = aExp - bExp; + aSig <<= 6; + bSig <<= 6; + if (0 < expDiff) { + if (aExp == 0xFF) { + return a; + } + if (bExp == 0) { + --expDiff; + } else { + bSig |= 0x20000000; + } + shift32RightJamming(bSig, expDiff, &bSig); + zExp = aExp; + } else if (expDiff < 0) { + if (bExp == 0xFF) { + return packFloat32(zSign, 0xFF, 0); + } + if (aExp == 0) { + ++expDiff; + } else { + aSig |= 0x20000000; + } + shift32RightJamming(aSig, -expDiff, &aSig); + zExp = bExp; + } else { + if (aExp == 0xFF) { + return a; + } + if (aExp == 0) + return packFloat32(zSign, 0, (aSig + bSig) >> 6); + zSig = 0x40000000 + aSig + bSig; + zExp = aExp; + goto roundAndPack; + } + aSig |= 0x20000000; + zSig = (aSig + bSig) << 1; + --zExp; + if ((sbits32) zSig < 0) { + zSig = aSig + bSig; + ++zExp; + } + roundAndPack: + return roundAndPackFloat32(zSign, zExp, zSig); + +} + +float64 float64_sub(float64 a, float64 b) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign(a); + bSign = extractFloat64Sign(b); + if (aSign == bSign) { + return subFloat64Sigs(a, b, aSign); + } else { + return addFloat64Sigs(a, b, aSign); + } + +} + +float32 float32_sub(float32 a, float32 b) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign(a); + bSign = extractFloat32Sign(b); + if (aSign == bSign) { + return subFloat32Sigs(a, b, aSign); + } else { + return addFloat32Sigs(a, b, aSign); + } + +} + +float32 float32_add(float32 a, float32 b) +{ + flag aSign, bSign; + + aSign = extractFloat32Sign(a); + bSign = extractFloat32Sign(b); + if (aSign == bSign) { + return addFloat32Sigs(a, b, aSign); + } else { + return subFloat32Sigs(a, b, aSign); + } + +} + +float64 float64_add(float64 a, float64 b) +{ + flag aSign, bSign; + + aSign = extractFloat64Sign(a); + bSign = extractFloat64Sign(b); + if (aSign == bSign) { + return addFloat64Sigs(a, b, aSign); + } else { + return subFloat64Sigs(a, b, aSign); + } +} + +static void +normalizeFloat64Subnormal(bits64 aSig, int16 * zExpPtr, bits64 * zSigPtr) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros64(aSig) - 11; + *zSigPtr = aSig << shiftCount; + *zExpPtr = 1 - shiftCount; +} + +inline void add128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, + bits64 * z1Ptr) +{ + bits64 z1; + + z1 = a1 + b1; + *z1Ptr = z1; + *z0Ptr = a0 + b0 + (z1 < a1); +} + +inline void +sub128(bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 * z0Ptr, + bits64 * z1Ptr) +{ + *z1Ptr = a1 - b1; + *z0Ptr = a0 - b0 - (a1 < b1); +} + +static bits64 estimateDiv128To64(bits64 a0, bits64 a1, bits64 b) +{ + bits64 b0, b1; + bits64 rem0, rem1, term0, term1; + bits64 z; + if (b <= a0) + return LIT64(0xFFFFFFFFFFFFFFFF); + b0 = b >> 32; + z = (b0 << 32 <= a0) ? LIT64(0xFFFFFFFF00000000) : (a0 / b0) << 32; + mul64To128(b, z, &term0, &term1); + sub128(a0, a1, term0, term1, &rem0, &rem1); + while (((sbits64) rem0) < 0) { + z -= LIT64(0x100000000); + b1 = b << 32; + add128(rem0, rem1, b0, b1, &rem0, &rem1); + } + rem0 = (rem0 << 32) | (rem1 >> 32); + z |= (b0 << 32 <= rem0) ? 0xFFFFFFFF : rem0 / b0; + return z; +} + +inline void mul64To128(bits64 a, bits64 b, bits64 * z0Ptr, bits64 * z1Ptr) +{ + bits32 aHigh, aLow, bHigh, bLow; + bits64 z0, zMiddleA, zMiddleB, z1; + + aLow = a; + aHigh = a >> 32; + bLow = b; + bHigh = b >> 32; + z1 = ((bits64) aLow) * bLow; + zMiddleA = ((bits64) aLow) * bHigh; + zMiddleB = ((bits64) aHigh) * bLow; + z0 = ((bits64) aHigh) * bHigh; + zMiddleA += zMiddleB; + z0 += (((bits64) (zMiddleA < zMiddleB)) << 32) + (zMiddleA >> 32); + zMiddleA <<= 32; + z1 += zMiddleA; + z0 += (z1 < zMiddleA); + *z1Ptr = z1; + *z0Ptr = z0; + +} + +static void normalizeFloat32Subnormal(bits32 aSig, int16 * zExpPtr, + bits32 * zSigPtr) +{ + int8 shiftCount; + + shiftCount = countLeadingZeros32(aSig) - 8; + *zSigPtr = aSig << shiftCount; + *zExpPtr = 1 - shiftCount; + +} + +float64 float64_div(float64 a, float64 b) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits64 aSig, bSig, zSig; + bits64 rem0, rem1; + bits64 term0, term1; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + bSign = extractFloat64Sign(b); + zSign = aSign ^ bSign; + if (aExp == 0x7FF) { + if (bExp == 0x7FF) { + } + return packFloat64(zSign, 0x7FF, 0); + } + if (bExp == 0x7FF) { + return packFloat64(zSign, 0, 0); + } + if (bExp == 0) { + if (bSig == 0) { + if ((aExp | aSig) == 0) { + float_raise(FPSCR_CAUSE_INVALID); + } + return packFloat64(zSign, 0x7FF, 0); + } + normalizeFloat64Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig == 0) + return packFloat64(zSign, 0, 0); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + zExp = aExp - bExp + 0x3FD; + aSig = (aSig | LIT64(0x0010000000000000)) << 10; + bSig = (bSig | LIT64(0x0010000000000000)) << 11; + if (bSig <= (aSig + aSig)) { + aSig >>= 1; + ++zExp; + } + zSig = estimateDiv128To64(aSig, 0, bSig); + if ((zSig & 0x1FF) <= 2) { + mul64To128(bSig, zSig, &term0, &term1); + sub128(aSig, 0, term0, term1, &rem0, &rem1); + while ((sbits64) rem0 < 0) { + --zSig; + add128(rem0, rem1, 0, bSig, &rem0, &rem1); + } + zSig |= (rem1 != 0); + } + return roundAndPackFloat64(zSign, zExp, zSig); + +} + +float32 float32_div(float32 a, float32 b) +{ + flag aSign, bSign, zSign; + int16 aExp, bExp, zExp; + bits32 aSig, bSig, zSig; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + bSign = extractFloat32Sign(b); + zSign = aSign ^ bSign; + if (aExp == 0xFF) { + if (bExp == 0xFF) { + } + return packFloat32(zSign, 0xFF, 0); + } + if (bExp == 0xFF) { + return packFloat32(zSign, 0, 0); + } + if (bExp == 0) { + if (bSig == 0) { + return packFloat32(zSign, 0xFF, 0); + } + normalizeFloat32Subnormal(bSig, &bExp, &bSig); + } + if (aExp == 0) { + if (aSig == 0) + return packFloat32(zSign, 0, 0); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + zExp = aExp - bExp + 0x7D; + aSig = (aSig | 0x00800000) << 7; + bSig = (bSig | 0x00800000) << 8; + if (bSig <= (aSig + aSig)) { + aSig >>= 1; + ++zExp; + } + zSig = (((bits64) aSig) << 32) / bSig; + if ((zSig & 0x3F) == 0) { + zSig |= (((bits64) bSig) * zSig != ((bits64) aSig) << 32); + } + return roundAndPackFloat32(zSign, zExp, zSig); + +} + +float32 float32_mul(float32 a, float32 b) +{ + char aSign, bSign, zSign; + int aExp, bExp, zExp; + unsigned int aSig, bSig; + unsigned long long zSig64; + unsigned int zSig; + + aSig = extractFloat32Frac(a); + aExp = extractFloat32Exp(a); + aSign = extractFloat32Sign(a); + bSig = extractFloat32Frac(b); + bExp = extractFloat32Exp(b); + bSign = extractFloat32Sign(b); + zSign = aSign ^ bSign; + if (aExp == 0) { + if (aSig == 0) + return packFloat32(zSign, 0, 0); + normalizeFloat32Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) + return packFloat32(zSign, 0, 0); + normalizeFloat32Subnormal(bSig, &bExp, &bSig); + } + if ((bExp == 0xff && bSig == 0) || (aExp == 0xff && aSig == 0)) + return roundAndPackFloat32(zSign, 0xff, 0); + + zExp = aExp + bExp - 0x7F; + aSig = (aSig | 0x00800000) << 7; + bSig = (bSig | 0x00800000) << 8; + shift64RightJamming(((unsigned long long)aSig) * bSig, 32, &zSig64); + zSig = zSig64; + if (0 <= (signed int)(zSig << 1)) { + zSig <<= 1; + --zExp; + } + return roundAndPackFloat32(zSign, zExp, zSig); + +} + +float64 float64_mul(float64 a, float64 b) +{ + char aSign, bSign, zSign; + int aExp, bExp, zExp; + unsigned long long int aSig, bSig, zSig0, zSig1; + + aSig = extractFloat64Frac(a); + aExp = extractFloat64Exp(a); + aSign = extractFloat64Sign(a); + bSig = extractFloat64Frac(b); + bExp = extractFloat64Exp(b); + bSign = extractFloat64Sign(b); + zSign = aSign ^ bSign; + + if (aExp == 0) { + if (aSig == 0) + return packFloat64(zSign, 0, 0); + normalizeFloat64Subnormal(aSig, &aExp, &aSig); + } + if (bExp == 0) { + if (bSig == 0) + return packFloat64(zSign, 0, 0); + normalizeFloat64Subnormal(bSig, &bExp, &bSig); + } + if ((aExp == 0x7ff && aSig == 0) || (bExp == 0x7ff && bSig == 0)) + return roundAndPackFloat64(zSign, 0x7ff, 0); + + zExp = aExp + bExp - 0x3FF; + aSig = (aSig | 0x0010000000000000LL) << 10; + bSig = (bSig | 0x0010000000000000LL) << 11; + mul64To128(aSig, bSig, &zSig0, &zSig1); + zSig0 |= (zSig1 != 0); + if (0 <= (signed long long int)(zSig0 << 1)) { + zSig0 <<= 1; + --zExp; + } + return roundAndPackFloat64(zSign, zExp, zSig0); +} diff -puN /dev/null arch/sh/kernel/cpu/sh5/Makefile --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/Makefile @@ -0,0 +1,7 @@ +# +# Makefile for the Linux/SuperH SH-5 backends. +# +obj-y := entry.o probe.o switchto.o + +obj-$(CONFIG_SH_FPU) += fpu.o +obj-$(CONFIG_KALLSYMS) += unwind.o diff -puN /dev/null arch/sh/kernel/cpu/sh5/entry.S --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/entry.S @@ -0,0 +1,2101 @@ +/* + * arch/sh/kernel/cpu/sh5/entry.S + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2004 - 2007 Paul Mundt + * Copyright (C) 2003, 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include + +/* + * SR fields. + */ +#define SR_ASID_MASK 0x00ff0000 +#define SR_FD_MASK 0x00008000 +#define SR_SS 0x08000000 +#define SR_BL 0x10000000 +#define SR_MD 0x40000000 + +/* + * Event code. + */ +#define EVENT_INTERRUPT 0 +#define EVENT_FAULT_TLB 1 +#define EVENT_FAULT_NOT_TLB 2 +#define EVENT_DEBUG 3 + +/* EXPEVT values */ +#define RESET_CAUSE 0x20 +#define DEBUGSS_CAUSE 0x980 + +/* + * Frame layout. Quad index. + */ +#define FRAME_T(x) FRAME_TBASE+(x*8) +#define FRAME_R(x) FRAME_RBASE+(x*8) +#define FRAME_S(x) FRAME_SBASE+(x*8) +#define FSPC 0 +#define FSSR 1 +#define FSYSCALL_ID 2 + +/* Arrange the save frame to be a multiple of 32 bytes long */ +#define FRAME_SBASE 0 +#define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */ +#define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */ +#define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */ +#define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */ + +#define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */ +#define FP_FRAME_BASE 0 + +#define SAVED_R2 0*8 +#define SAVED_R3 1*8 +#define SAVED_R4 2*8 +#define SAVED_R5 3*8 +#define SAVED_R18 4*8 +#define SAVED_R6 5*8 +#define SAVED_TR0 6*8 + +/* These are the registers saved in the TLB path that aren't saved in the first + level of the normal one. */ +#define TLB_SAVED_R25 7*8 +#define TLB_SAVED_TR1 8*8 +#define TLB_SAVED_TR2 9*8 +#define TLB_SAVED_TR3 10*8 +#define TLB_SAVED_TR4 11*8 +/* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing + breakage otherwise. */ +#define TLB_SAVED_R0 12*8 +#define TLB_SAVED_R1 13*8 + +#define CLI() \ + getcon SR, r6; \ + ori r6, 0xf0, r6; \ + putcon r6, SR; + +#define STI() \ + getcon SR, r6; \ + andi r6, ~0xf0, r6; \ + putcon r6, SR; + +#ifdef CONFIG_PREEMPT +# define preempt_stop() CLI() +#else +# define preempt_stop() +# define resume_kernel restore_all +#endif + + .section .data, "aw" + +#define FAST_TLBMISS_STACK_CACHELINES 4 +#define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES) + +/* Register back-up area for all exceptions */ + .balign 32 + /* Allow for 16 quadwords to be pushed by fast tlbmiss handling + * register saves etc. */ + .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0 +/* This is 32 byte aligned by construction */ +/* Register back-up area for all exceptions */ +reg_save_area: + .quad 0 + .quad 0 + .quad 0 + .quad 0 + + .quad 0 + .quad 0 + .quad 0 + .quad 0 + + .quad 0 + .quad 0 + .quad 0 + .quad 0 + + .quad 0 + .quad 0 + +/* Save area for RESVEC exceptions. We cannot use reg_save_area because of + * reentrancy. Note this area may be accessed via physical address. + * Align so this fits a whole single cache line, for ease of purging. + */ + .balign 32,0,32 +resvec_save_area: + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .quad 0 + .balign 32,0,32 + +/* Jump table of 3rd level handlers */ +trap_jtable: + .long do_exception_error /* 0x000 */ + .long do_exception_error /* 0x020 */ + .long tlb_miss_load /* 0x040 */ + .long tlb_miss_store /* 0x060 */ + ! ARTIFICIAL pseudo-EXPEVT setting + .long do_debug_interrupt /* 0x080 */ + .long tlb_miss_load /* 0x0A0 */ + .long tlb_miss_store /* 0x0C0 */ + .long do_address_error_load /* 0x0E0 */ + .long do_address_error_store /* 0x100 */ +#ifdef CONFIG_SH_FPU + .long do_fpu_error /* 0x120 */ +#else + .long do_exception_error /* 0x120 */ +#endif + .long do_exception_error /* 0x140 */ + .long system_call /* 0x160 */ + .long do_reserved_inst /* 0x180 */ + .long do_illegal_slot_inst /* 0x1A0 */ + .long do_exception_error /* 0x1C0 - NMI */ + .long do_exception_error /* 0x1E0 */ + .rept 15 + .long do_IRQ /* 0x200 - 0x3C0 */ + .endr + .long do_exception_error /* 0x3E0 */ + .rept 32 + .long do_IRQ /* 0x400 - 0x7E0 */ + .endr + .long fpu_error_or_IRQA /* 0x800 */ + .long fpu_error_or_IRQB /* 0x820 */ + .long do_IRQ /* 0x840 */ + .long do_IRQ /* 0x860 */ + .rept 6 + .long do_exception_error /* 0x880 - 0x920 */ + .endr + .long do_software_break_point /* 0x940 */ + .long do_exception_error /* 0x960 */ + .long do_single_step /* 0x980 */ + + .rept 3 + .long do_exception_error /* 0x9A0 - 0x9E0 */ + .endr + .long do_IRQ /* 0xA00 */ + .long do_IRQ /* 0xA20 */ + .long itlb_miss_or_IRQ /* 0xA40 */ + .long do_IRQ /* 0xA60 */ + .long do_IRQ /* 0xA80 */ + .long itlb_miss_or_IRQ /* 0xAA0 */ + .long do_exception_error /* 0xAC0 */ + .long do_address_error_exec /* 0xAE0 */ + .rept 8 + .long do_exception_error /* 0xB00 - 0xBE0 */ + .endr + .rept 18 + .long do_IRQ /* 0xC00 - 0xE20 */ + .endr + + .section .text64, "ax" + +/* + * --- Exception/Interrupt/Event Handling Section + */ + +/* + * VBR and RESVEC blocks. + * + * First level handler for VBR-based exceptions. + * + * To avoid waste of space, align to the maximum text block size. + * This is assumed to be at most 128 bytes or 32 instructions. + * DO NOT EXCEED 32 instructions on the first level handlers ! + * + * Also note that RESVEC is contained within the VBR block + * where the room left (1KB - TEXT_SIZE) allows placing + * the RESVEC block (at most 512B + TEXT_SIZE). + * + * So first (and only) level handler for RESVEC-based exceptions. + * + * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss + * and interrupt) we are a lot tight with register space until + * saving onto the stack frame, which is done in handle_exception(). + * + */ + +#define TEXT_SIZE 128 +#define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */ + + .balign TEXT_SIZE +LVBR_block: + .space 256, 0 /* Power-on class handler, */ + /* not required here */ +not_a_tlb_miss: + synco /* TAKum03020 (but probably a good idea anyway.) */ + /* Save original stack pointer into KCR1 */ + putcon SP, KCR1 + + /* Save other original registers into reg_save_area */ + movi reg_save_area, SP + st.q SP, SAVED_R2, r2 + st.q SP, SAVED_R3, r3 + st.q SP, SAVED_R4, r4 + st.q SP, SAVED_R5, r5 + st.q SP, SAVED_R6, r6 + st.q SP, SAVED_R18, r18 + gettr tr0, r3 + st.q SP, SAVED_TR0, r3 + + /* Set args for Non-debug, Not a TLB miss class handler */ + getcon EXPEVT, r2 + movi ret_from_exception, r3 + ori r3, 1, r3 + movi EVENT_FAULT_NOT_TLB, r4 + or SP, ZERO, r5 + getcon KCR1, SP + pta handle_exception, tr0 + blink tr0, ZERO + + .balign 256 + ! VBR+0x200 + nop + .balign 256 + ! VBR+0x300 + nop + .balign 256 + /* + * Instead of the natural .balign 1024 place RESVEC here + * respecting the final 1KB alignment. + */ + .balign TEXT_SIZE + /* + * Instead of '.space 1024-TEXT_SIZE' place the RESVEC + * block making sure the final alignment is correct. + */ +tlb_miss: + synco /* TAKum03020 (but probably a good idea anyway.) */ + putcon SP, KCR1 + movi reg_save_area, SP + /* SP is guaranteed 32-byte aligned. */ + st.q SP, TLB_SAVED_R0 , r0 + st.q SP, TLB_SAVED_R1 , r1 + st.q SP, SAVED_R2 , r2 + st.q SP, SAVED_R3 , r3 + st.q SP, SAVED_R4 , r4 + st.q SP, SAVED_R5 , r5 + st.q SP, SAVED_R6 , r6 + st.q SP, SAVED_R18, r18 + + /* Save R25 for safety; as/ld may want to use it to achieve the call to + * the code in mm/tlbmiss.c */ + st.q SP, TLB_SAVED_R25, r25 + gettr tr0, r2 + gettr tr1, r3 + gettr tr2, r4 + gettr tr3, r5 + gettr tr4, r18 + st.q SP, SAVED_TR0 , r2 + st.q SP, TLB_SAVED_TR1 , r3 + st.q SP, TLB_SAVED_TR2 , r4 + st.q SP, TLB_SAVED_TR3 , r5 + st.q SP, TLB_SAVED_TR4 , r18 + + pt do_fast_page_fault, tr0 + getcon SSR, r2 + getcon EXPEVT, r3 + getcon TEA, r4 + shlri r2, 30, r2 + andi r2, 1, r2 /* r2 = SSR.MD */ + blink tr0, LINK + + pt fixup_to_invoke_general_handler, tr1 + + /* If the fast path handler fixed the fault, just drop through quickly + to the restore code right away to return to the excepting context. + */ + beqi/u r2, 0, tr1 + +fast_tlb_miss_restore: + ld.q SP, SAVED_TR0, r2 + ld.q SP, TLB_SAVED_TR1, r3 + ld.q SP, TLB_SAVED_TR2, r4 + + ld.q SP, TLB_SAVED_TR3, r5 + ld.q SP, TLB_SAVED_TR4, r18 + + ptabs r2, tr0 + ptabs r3, tr1 + ptabs r4, tr2 + ptabs r5, tr3 + ptabs r18, tr4 + + ld.q SP, TLB_SAVED_R0, r0 + ld.q SP, TLB_SAVED_R1, r1 + ld.q SP, SAVED_R2, r2 + ld.q SP, SAVED_R3, r3 + ld.q SP, SAVED_R4, r4 + ld.q SP, SAVED_R5, r5 + ld.q SP, SAVED_R6, r6 + ld.q SP, SAVED_R18, r18 + ld.q SP, TLB_SAVED_R25, r25 + + getcon KCR1, SP + rte + nop /* for safety, in case the code is run on sh5-101 cut1.x */ + +fixup_to_invoke_general_handler: + + /* OK, new method. Restore stuff that's not expected to get saved into + the 'first-level' reg save area, then just fall through to setting + up the registers and calling the second-level handler. */ + + /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore + r25,tr1-4 and save r6 to get into the right state. */ + + ld.q SP, TLB_SAVED_TR1, r3 + ld.q SP, TLB_SAVED_TR2, r4 + ld.q SP, TLB_SAVED_TR3, r5 + ld.q SP, TLB_SAVED_TR4, r18 + ld.q SP, TLB_SAVED_R25, r25 + + ld.q SP, TLB_SAVED_R0, r0 + ld.q SP, TLB_SAVED_R1, r1 + + ptabs/u r3, tr1 + ptabs/u r4, tr2 + ptabs/u r5, tr3 + ptabs/u r18, tr4 + + /* Set args for Non-debug, TLB miss class handler */ + getcon EXPEVT, r2 + movi ret_from_exception, r3 + ori r3, 1, r3 + movi EVENT_FAULT_TLB, r4 + or SP, ZERO, r5 + getcon KCR1, SP + pta handle_exception, tr0 + blink tr0, ZERO + +/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE + DOES END UP AT VBR+0x600 */ + nop + nop + nop + nop + nop + nop + + .balign 256 + /* VBR + 0x600 */ + +interrupt: + synco /* TAKum03020 (but probably a good idea anyway.) */ + /* Save original stack pointer into KCR1 */ + putcon SP, KCR1 + + /* Save other original registers into reg_save_area */ + movi reg_save_area, SP + st.q SP, SAVED_R2, r2 + st.q SP, SAVED_R3, r3 + st.q SP, SAVED_R4, r4 + st.q SP, SAVED_R5, r5 + st.q SP, SAVED_R6, r6 + st.q SP, SAVED_R18, r18 + gettr tr0, r3 + st.q SP, SAVED_TR0, r3 + + /* Set args for interrupt class handler */ + getcon INTEVT, r2 + movi ret_from_irq, r3 + ori r3, 1, r3 + movi EVENT_INTERRUPT, r4 + or SP, ZERO, r5 + getcon KCR1, SP + pta handle_exception, tr0 + blink tr0, ZERO + .balign TEXT_SIZE /* let's waste the bare minimum */ + +LVBR_block_end: /* Marker. Used for total checking */ + + .balign 256 +LRESVEC_block: + /* Panic handler. Called with MMU off. Possible causes/actions: + * - Reset: Jump to program start. + * - Single Step: Turn off Single Step & return. + * - Others: Call panic handler, passing PC as arg. + * (this may need to be extended...) + */ +reset_or_panic: + synco /* TAKum03020 (but probably a good idea anyway.) */ + putcon SP, DCR + /* First save r0-1 and tr0, as we need to use these */ + movi resvec_save_area-CONFIG_PAGE_OFFSET, SP + st.q SP, 0, r0 + st.q SP, 8, r1 + gettr tr0, r0 + st.q SP, 32, r0 + + /* Check cause */ + getcon EXPEVT, r0 + movi RESET_CAUSE, r1 + sub r1, r0, r1 /* r1=0 if reset */ + movi _stext-CONFIG_PAGE_OFFSET, r0 + ori r0, 1, r0 + ptabs r0, tr0 + beqi r1, 0, tr0 /* Jump to start address if reset */ + + getcon EXPEVT, r0 + movi DEBUGSS_CAUSE, r1 + sub r1, r0, r1 /* r1=0 if single step */ + pta single_step_panic, tr0 + beqi r1, 0, tr0 /* jump if single step */ + + /* Now jump to where we save the registers. */ + movi panic_stash_regs-CONFIG_PAGE_OFFSET, r1 + ptabs r1, tr0 + blink tr0, r63 + +single_step_panic: + /* We are in a handler with Single Step set. We need to resume the + * handler, by turning on MMU & turning off Single Step. */ + getcon SSR, r0 + movi SR_MMU, r1 + or r0, r1, r0 + movi ~SR_SS, r1 + and r0, r1, r0 + putcon r0, SSR + /* Restore EXPEVT, as the rte won't do this */ + getcon PEXPEVT, r0 + putcon r0, EXPEVT + /* Restore regs */ + ld.q SP, 32, r0 + ptabs r0, tr0 + ld.q SP, 0, r0 + ld.q SP, 8, r1 + getcon DCR, SP + synco + rte + + + .balign 256 +debug_exception: + synco /* TAKum03020 (but probably a good idea anyway.) */ + /* + * Single step/software_break_point first level handler. + * Called with MMU off, so the first thing we do is enable it + * by doing an rte with appropriate SSR. + */ + putcon SP, DCR + /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */ + movi resvec_save_area-CONFIG_PAGE_OFFSET, SP + + /* With the MMU off, we are bypassing the cache, so purge any + * data that will be made stale by the following stores. + */ + ocbp SP, 0 + synco + + st.q SP, 0, r0 + st.q SP, 8, r1 + getcon SPC, r0 + st.q SP, 16, r0 + getcon SSR, r0 + st.q SP, 24, r0 + + /* Enable MMU, block exceptions, set priv mode, disable single step */ + movi SR_MMU | SR_BL | SR_MD, r1 + or r0, r1, r0 + movi ~SR_SS, r1 + and r0, r1, r0 + putcon r0, SSR + /* Force control to debug_exception_2 when rte is executed */ + movi debug_exeception_2, r0 + ori r0, 1, r0 /* force SHmedia, just in case */ + putcon r0, SPC + getcon DCR, SP + synco + rte +debug_exeception_2: + /* Restore saved regs */ + putcon SP, KCR1 + movi resvec_save_area, SP + ld.q SP, 24, r0 + putcon r0, SSR + ld.q SP, 16, r0 + putcon r0, SPC + ld.q SP, 0, r0 + ld.q SP, 8, r1 + + /* Save other original registers into reg_save_area */ + movi reg_save_area, SP + st.q SP, SAVED_R2, r2 + st.q SP, SAVED_R3, r3 + st.q SP, SAVED_R4, r4 + st.q SP, SAVED_R5, r5 + st.q SP, SAVED_R6, r6 + st.q SP, SAVED_R18, r18 + gettr tr0, r3 + st.q SP, SAVED_TR0, r3 + + /* Set args for debug class handler */ + getcon EXPEVT, r2 + movi ret_from_exception, r3 + ori r3, 1, r3 + movi EVENT_DEBUG, r4 + or SP, ZERO, r5 + getcon KCR1, SP + pta handle_exception, tr0 + blink tr0, ZERO + + .balign 256 +debug_interrupt: + /* !!! WE COME HERE IN REAL MODE !!! */ + /* Hook-up debug interrupt to allow various debugging options to be + * hooked into its handler. */ + /* Save original stack pointer into KCR1 */ + synco + putcon SP, KCR1 + movi resvec_save_area-CONFIG_PAGE_OFFSET, SP + ocbp SP, 0 + ocbp SP, 32 + synco + + /* Save other original registers into reg_save_area thru real addresses */ + st.q SP, SAVED_R2, r2 + st.q SP, SAVED_R3, r3 + st.q SP, SAVED_R4, r4 + st.q SP, SAVED_R5, r5 + st.q SP, SAVED_R6, r6 + st.q SP, SAVED_R18, r18 + gettr tr0, r3 + st.q SP, SAVED_TR0, r3 + + /* move (spc,ssr)->(pspc,pssr). The rte will shift + them back again, so that they look like the originals + as far as the real handler code is concerned. */ + getcon spc, r6 + putcon r6, pspc + getcon ssr, r6 + putcon r6, pssr + + ! construct useful SR for handle_exception + movi 3, r6 + shlli r6, 30, r6 + getcon sr, r18 + or r18, r6, r6 + putcon r6, ssr + + ! SSR is now the current SR with the MD and MMU bits set + ! i.e. the rte will switch back to priv mode and put + ! the mmu back on + + ! construct spc + movi handle_exception, r18 + ori r18, 1, r18 ! for safety (do we need this?) + putcon r18, spc + + /* Set args for Non-debug, Not a TLB miss class handler */ + + ! EXPEVT==0x80 is unused, so 'steal' this value to put the + ! debug interrupt handler in the vectoring table + movi 0x80, r2 + movi ret_from_exception, r3 + ori r3, 1, r3 + movi EVENT_FAULT_NOT_TLB, r4 + + or SP, ZERO, r5 + movi CONFIG_PAGE_OFFSET, r6 + add r6, r5, r5 + getcon KCR1, SP + + synco ! for safety + rte ! -> handle_exception, switch back to priv mode again + +LRESVEC_block_end: /* Marker. Unused. */ + + .balign TEXT_SIZE + +/* + * Second level handler for VBR-based exceptions. Pre-handler. + * In common to all stack-frame sensitive handlers. + * + * Inputs: + * (KCR0) Current [current task union] + * (KCR1) Original SP + * (r2) INTEVT/EXPEVT + * (r3) appropriate return address + * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug) + * (r5) Pointer to reg_save_area + * (SP) Original SP + * + * Available registers: + * (r6) + * (r18) + * (tr0) + * + */ +handle_exception: + /* Common 2nd level handler. */ + + /* First thing we need an appropriate stack pointer */ + getcon SSR, r6 + shlri r6, 30, r6 + andi r6, 1, r6 + pta stack_ok, tr0 + bne r6, ZERO, tr0 /* Original stack pointer is fine */ + + /* Set stack pointer for user fault */ + getcon KCR0, SP + movi THREAD_SIZE, r6 /* Point to the end */ + add SP, r6, SP + +stack_ok: + +/* DEBUG : check for underflow/overflow of the kernel stack */ + pta no_underflow, tr0 + getcon KCR0, r6 + movi 1024, r18 + add r6, r18, r6 + bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone + +/* Just panic to cause a crash. */ +bad_sp: + ld.b r63, 0, r6 + nop + +no_underflow: + pta bad_sp, tr0 + getcon kcr0, r6 + movi THREAD_SIZE, r18 + add r18, r6, r6 + bgt SP, r6, tr0 ! sp above the stack + + /* Make some room for the BASIC frame. */ + movi -(FRAME_SIZE), r6 + add SP, r6, SP + +/* Could do this with no stalling if we had another spare register, but the + code below will be OK. */ + ld.q r5, SAVED_R2, r6 + ld.q r5, SAVED_R3, r18 + st.q SP, FRAME_R(2), r6 + ld.q r5, SAVED_R4, r6 + st.q SP, FRAME_R(3), r18 + ld.q r5, SAVED_R5, r18 + st.q SP, FRAME_R(4), r6 + ld.q r5, SAVED_R6, r6 + st.q SP, FRAME_R(5), r18 + ld.q r5, SAVED_R18, r18 + st.q SP, FRAME_R(6), r6 + ld.q r5, SAVED_TR0, r6 + st.q SP, FRAME_R(18), r18 + st.q SP, FRAME_T(0), r6 + + /* Keep old SP around */ + getcon KCR1, r6 + + /* Save the rest of the general purpose registers */ + st.q SP, FRAME_R(0), r0 + st.q SP, FRAME_R(1), r1 + st.q SP, FRAME_R(7), r7 + st.q SP, FRAME_R(8), r8 + st.q SP, FRAME_R(9), r9 + st.q SP, FRAME_R(10), r10 + st.q SP, FRAME_R(11), r11 + st.q SP, FRAME_R(12), r12 + st.q SP, FRAME_R(13), r13 + st.q SP, FRAME_R(14), r14 + + /* SP is somewhere else */ + st.q SP, FRAME_R(15), r6 + + st.q SP, FRAME_R(16), r16 + st.q SP, FRAME_R(17), r17 + /* r18 is saved earlier. */ + st.q SP, FRAME_R(19), r19 + st.q SP, FRAME_R(20), r20 + st.q SP, FRAME_R(21), r21 + st.q SP, FRAME_R(22), r22 + st.q SP, FRAME_R(23), r23 + st.q SP, FRAME_R(24), r24 + st.q SP, FRAME_R(25), r25 + st.q SP, FRAME_R(26), r26 + st.q SP, FRAME_R(27), r27 + st.q SP, FRAME_R(28), r28 + st.q SP, FRAME_R(29), r29 + st.q SP, FRAME_R(30), r30 + st.q SP, FRAME_R(31), r31 + st.q SP, FRAME_R(32), r32 + st.q SP, FRAME_R(33), r33 + st.q SP, FRAME_R(34), r34 + st.q SP, FRAME_R(35), r35 + st.q SP, FRAME_R(36), r36 + st.q SP, FRAME_R(37), r37 + st.q SP, FRAME_R(38), r38 + st.q SP, FRAME_R(39), r39 + st.q SP, FRAME_R(40), r40 + st.q SP, FRAME_R(41), r41 + st.q SP, FRAME_R(42), r42 + st.q SP, FRAME_R(43), r43 + st.q SP, FRAME_R(44), r44 + st.q SP, FRAME_R(45), r45 + st.q SP, FRAME_R(46), r46 + st.q SP, FRAME_R(47), r47 + st.q SP, FRAME_R(48), r48 + st.q SP, FRAME_R(49), r49 + st.q SP, FRAME_R(50), r50 + st.q SP, FRAME_R(51), r51 + st.q SP, FRAME_R(52), r52 + st.q SP, FRAME_R(53), r53 + st.q SP, FRAME_R(54), r54 + st.q SP, FRAME_R(55), r55 + st.q SP, FRAME_R(56), r56 + st.q SP, FRAME_R(57), r57 + st.q SP, FRAME_R(58), r58 + st.q SP, FRAME_R(59), r59 + st.q SP, FRAME_R(60), r60 + st.q SP, FRAME_R(61), r61 + st.q SP, FRAME_R(62), r62 + + /* + * Save the S* registers. + */ + getcon SSR, r61 + st.q SP, FRAME_S(FSSR), r61 + getcon SPC, r62 + st.q SP, FRAME_S(FSPC), r62 + movi -1, r62 /* Reset syscall_nr */ + st.q SP, FRAME_S(FSYSCALL_ID), r62 + + /* Save the rest of the target registers */ + gettr tr1, r6 + st.q SP, FRAME_T(1), r6 + gettr tr2, r6 + st.q SP, FRAME_T(2), r6 + gettr tr3, r6 + st.q SP, FRAME_T(3), r6 + gettr tr4, r6 + st.q SP, FRAME_T(4), r6 + gettr tr5, r6 + st.q SP, FRAME_T(5), r6 + gettr tr6, r6 + st.q SP, FRAME_T(6), r6 + gettr tr7, r6 + st.q SP, FRAME_T(7), r6 + + ! setup FP so that unwinder can wind back through nested kernel mode + ! exceptions + add SP, ZERO, r14 + +#ifdef CONFIG_POOR_MANS_STRACE + /* We've pushed all the registers now, so only r2-r4 hold anything + * useful. Move them into callee save registers */ + or r2, ZERO, r28 + or r3, ZERO, r29 + or r4, ZERO, r30 + + /* Preserve r2 as the event code */ + movi evt_debug, r3 + ori r3, 1, r3 + ptabs r3, tr0 + + or SP, ZERO, r6 + getcon TRA, r5 + blink tr0, LINK + + or r28, ZERO, r2 + or r29, ZERO, r3 + or r30, ZERO, r4 +#endif + + /* For syscall and debug race condition, get TRA now */ + getcon TRA, r5 + + /* We are in a safe position to turn SR.BL off, but set IMASK=0xf + * Also set FD, to catch FPU usage in the kernel. + * + * benedict.gaster@superh.com 29/07/2002 + * + * On all SH5-101 revisions it is unsafe to raise the IMASK and at the + * same time change BL from 1->0, as any pending interrupt of a level + * higher than he previous value of IMASK will leak through and be + * taken unexpectedly. + * + * To avoid this we raise the IMASK and then issue another PUTCON to + * enable interrupts. + */ + getcon SR, r6 + movi SR_IMASK | SR_FD, r7 + or r6, r7, r6 + putcon r6, SR + movi SR_UNBLOCK_EXC, r7 + and r6, r7, r6 + putcon r6, SR + + + /* Now call the appropriate 3rd level handler */ + or r3, ZERO, LINK + movi trap_jtable, r3 + shlri r2, 3, r2 + ldx.l r2, r3, r3 + shlri r2, 2, r2 + ptabs r3, tr0 + or SP, ZERO, r3 + blink tr0, ZERO + +/* + * Second level handler for VBR-based exceptions. Post-handlers. + * + * Post-handlers for interrupts (ret_from_irq), exceptions + * (ret_from_exception) and common reentrance doors (restore_all + * to get back to the original context, ret_from_syscall loop to + * check kernel exiting). + * + * ret_with_reschedule and work_notifysig are an inner lables of + * the ret_from_syscall loop. + * + * In common to all stack-frame sensitive handlers. + * + * Inputs: + * (SP) struct pt_regs *, original register's frame pointer (basic) + * + */ + .global ret_from_irq +ret_from_irq: +#ifdef CONFIG_POOR_MANS_STRACE + pta evt_debug_ret_from_irq, tr0 + ori SP, 0, r2 + blink tr0, LINK +#endif + ld.q SP, FRAME_S(FSSR), r6 + shlri r6, 30, r6 + andi r6, 1, r6 + pta resume_kernel, tr0 + bne r6, ZERO, tr0 /* no further checks */ + STI() + pta ret_with_reschedule, tr0 + blink tr0, ZERO /* Do not check softirqs */ + + .global ret_from_exception +ret_from_exception: + preempt_stop() + +#ifdef CONFIG_POOR_MANS_STRACE + pta evt_debug_ret_from_exc, tr0 + ori SP, 0, r2 + blink tr0, LINK +#endif + + ld.q SP, FRAME_S(FSSR), r6 + shlri r6, 30, r6 + andi r6, 1, r6 + pta resume_kernel, tr0 + bne r6, ZERO, tr0 /* no further checks */ + + /* Check softirqs */ + +#ifdef CONFIG_PREEMPT + pta ret_from_syscall, tr0 + blink tr0, ZERO + +resume_kernel: + pta restore_all, tr0 + + getcon KCR0, r6 + ld.l r6, TI_PRE_COUNT, r7 + beq/u r7, ZERO, tr0 + +need_resched: + ld.l r6, TI_FLAGS, r7 + movi (1 << TIF_NEED_RESCHED), r8 + and r8, r7, r8 + bne r8, ZERO, tr0 + + getcon SR, r7 + andi r7, 0xf0, r7 + bne r7, ZERO, tr0 + + movi ((PREEMPT_ACTIVE >> 16) & 65535), r8 + shori (PREEMPT_ACTIVE & 65535), r8 + st.l r6, TI_PRE_COUNT, r8 + + STI() + movi schedule, r7 + ori r7, 1, r7 + ptabs r7, tr1 + blink tr1, LINK + + st.l r6, TI_PRE_COUNT, ZERO + CLI() + + pta need_resched, tr1 + blink tr1, ZERO +#endif + + .global ret_from_syscall +ret_from_syscall: + +ret_with_reschedule: + getcon KCR0, r6 ! r6 contains current_thread_info + ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags + + movi _TIF_NEED_RESCHED, r8 + and r8, r7, r8 + pta work_resched, tr0 + bne r8, ZERO, tr0 + + pta restore_all, tr1 + + movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 + and r8, r7, r8 + pta work_notifysig, tr0 + bne r8, ZERO, tr0 + + blink tr1, ZERO + +work_resched: + pta ret_from_syscall, tr0 + gettr tr0, LINK + movi schedule, r6 + ptabs r6, tr0 + blink tr0, ZERO /* Call schedule(), return on top */ + +work_notifysig: + gettr tr1, LINK + + movi do_signal, r6 + ptabs r6, tr0 + or SP, ZERO, r2 + or ZERO, ZERO, r3 + blink tr0, LINK /* Call do_signal(regs, 0), return here */ + +restore_all: + /* Do prefetches */ + + ld.q SP, FRAME_T(0), r6 + ld.q SP, FRAME_T(1), r7 + ld.q SP, FRAME_T(2), r8 + ld.q SP, FRAME_T(3), r9 + ptabs r6, tr0 + ptabs r7, tr1 + ptabs r8, tr2 + ptabs r9, tr3 + ld.q SP, FRAME_T(4), r6 + ld.q SP, FRAME_T(5), r7 + ld.q SP, FRAME_T(6), r8 + ld.q SP, FRAME_T(7), r9 + ptabs r6, tr4 + ptabs r7, tr5 + ptabs r8, tr6 + ptabs r9, tr7 + + ld.q SP, FRAME_R(0), r0 + ld.q SP, FRAME_R(1), r1 + ld.q SP, FRAME_R(2), r2 + ld.q SP, FRAME_R(3), r3 + ld.q SP, FRAME_R(4), r4 + ld.q SP, FRAME_R(5), r5 + ld.q SP, FRAME_R(6), r6 + ld.q SP, FRAME_R(7), r7 + ld.q SP, FRAME_R(8), r8 + ld.q SP, FRAME_R(9), r9 + ld.q SP, FRAME_R(10), r10 + ld.q SP, FRAME_R(11), r11 + ld.q SP, FRAME_R(12), r12 + ld.q SP, FRAME_R(13), r13 + ld.q SP, FRAME_R(14), r14 + + ld.q SP, FRAME_R(16), r16 + ld.q SP, FRAME_R(17), r17 + ld.q SP, FRAME_R(18), r18 + ld.q SP, FRAME_R(19), r19 + ld.q SP, FRAME_R(20), r20 + ld.q SP, FRAME_R(21), r21 + ld.q SP, FRAME_R(22), r22 + ld.q SP, FRAME_R(23), r23 + ld.q SP, FRAME_R(24), r24 + ld.q SP, FRAME_R(25), r25 + ld.q SP, FRAME_R(26), r26 + ld.q SP, FRAME_R(27), r27 + ld.q SP, FRAME_R(28), r28 + ld.q SP, FRAME_R(29), r29 + ld.q SP, FRAME_R(30), r30 + ld.q SP, FRAME_R(31), r31 + ld.q SP, FRAME_R(32), r32 + ld.q SP, FRAME_R(33), r33 + ld.q SP, FRAME_R(34), r34 + ld.q SP, FRAME_R(35), r35 + ld.q SP, FRAME_R(36), r36 + ld.q SP, FRAME_R(37), r37 + ld.q SP, FRAME_R(38), r38 + ld.q SP, FRAME_R(39), r39 + ld.q SP, FRAME_R(40), r40 + ld.q SP, FRAME_R(41), r41 + ld.q SP, FRAME_R(42), r42 + ld.q SP, FRAME_R(43), r43 + ld.q SP, FRAME_R(44), r44 + ld.q SP, FRAME_R(45), r45 + ld.q SP, FRAME_R(46), r46 + ld.q SP, FRAME_R(47), r47 + ld.q SP, FRAME_R(48), r48 + ld.q SP, FRAME_R(49), r49 + ld.q SP, FRAME_R(50), r50 + ld.q SP, FRAME_R(51), r51 + ld.q SP, FRAME_R(52), r52 + ld.q SP, FRAME_R(53), r53 + ld.q SP, FRAME_R(54), r54 + ld.q SP, FRAME_R(55), r55 + ld.q SP, FRAME_R(56), r56 + ld.q SP, FRAME_R(57), r57 + ld.q SP, FRAME_R(58), r58 + + getcon SR, r59 + movi SR_BLOCK_EXC, r60 + or r59, r60, r59 + putcon r59, SR /* SR.BL = 1, keep nesting out */ + ld.q SP, FRAME_S(FSSR), r61 + ld.q SP, FRAME_S(FSPC), r62 + movi SR_ASID_MASK, r60 + and r59, r60, r59 + andc r61, r60, r61 /* Clear out older ASID */ + or r59, r61, r61 /* Retain current ASID */ + putcon r61, SSR + putcon r62, SPC + + /* Ignore FSYSCALL_ID */ + + ld.q SP, FRAME_R(59), r59 + ld.q SP, FRAME_R(60), r60 + ld.q SP, FRAME_R(61), r61 + ld.q SP, FRAME_R(62), r62 + + /* Last touch */ + ld.q SP, FRAME_R(15), SP + rte + nop + +/* + * Third level handlers for VBR-based exceptions. Adapting args to + * and/or deflecting to fourth level handlers. + * + * Fourth level handlers interface. + * Most are C-coded handlers directly pointed by the trap_jtable. + * (Third = Fourth level) + * Inputs: + * (r2) fault/interrupt code, entry number (e.g. NMI = 14, + * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) + * (r3) struct pt_regs *, original register's frame pointer + * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) + * (r5) TRA control register (for syscall/debug benefit only) + * (LINK) return address + * (SP) = r3 + * + * Kernel TLB fault handlers will get a slightly different interface. + * (r2) struct pt_regs *, original register's frame pointer + * (r3) writeaccess, whether it's a store fault as opposed to load fault + * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault + * (r5) Effective Address of fault + * (LINK) return address + * (SP) = r2 + * + * fpu_error_or_IRQ? is a helper to deflect to the right cause. + * + */ +tlb_miss_load: + or SP, ZERO, r2 + or ZERO, ZERO, r3 /* Read */ + or ZERO, ZERO, r4 /* Data */ + getcon TEA, r5 + pta call_do_page_fault, tr0 + beq ZERO, ZERO, tr0 + +tlb_miss_store: + or SP, ZERO, r2 + movi 1, r3 /* Write */ + or ZERO, ZERO, r4 /* Data */ + getcon TEA, r5 + pta call_do_page_fault, tr0 + beq ZERO, ZERO, tr0 + +itlb_miss_or_IRQ: + pta its_IRQ, tr0 + beqi/u r4, EVENT_INTERRUPT, tr0 + or SP, ZERO, r2 + or ZERO, ZERO, r3 /* Read */ + movi 1, r4 /* Text */ + getcon TEA, r5 + /* Fall through */ + +call_do_page_fault: + movi do_page_fault, r6 + ptabs r6, tr0 + blink tr0, ZERO + +fpu_error_or_IRQA: + pta its_IRQ, tr0 + beqi/l r4, EVENT_INTERRUPT, tr0 +#ifdef CONFIG_SH_FPU + movi do_fpu_state_restore, r6 +#else + movi do_exception_error, r6 +#endif + ptabs r6, tr0 + blink tr0, ZERO + +fpu_error_or_IRQB: + pta its_IRQ, tr0 + beqi/l r4, EVENT_INTERRUPT, tr0 +#ifdef CONFIG_SH_FPU + movi do_fpu_state_restore, r6 +#else + movi do_exception_error, r6 +#endif + ptabs r6, tr0 + blink tr0, ZERO + +its_IRQ: + movi do_IRQ, r6 + ptabs r6, tr0 + blink tr0, ZERO + +/* + * system_call/unknown_trap third level handler: + * + * Inputs: + * (r2) fault/interrupt code, entry number (TRAP = 11) + * (r3) struct pt_regs *, original register's frame pointer + * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) + * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) + * (SP) = r3 + * (LINK) return address: ret_from_exception + * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) + * + * Outputs: + * (*r3) Syscall reply (Saved r2) + * (LINK) In case of syscall only it can be scrapped. + * Common second level post handler will be ret_from_syscall. + * Common (non-trace) exit point to that is syscall_ret (saving + * result to r2). Common bad exit point is syscall_bad (returning + * ENOSYS then saved to r2). + * + */ + +unknown_trap: + /* Unknown Trap or User Trace */ + movi do_unknown_trapa, r6 + ptabs r6, tr0 + ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */ + andi r2, 0x1ff, r2 /* r2 = syscall # */ + blink tr0, LINK + + pta syscall_ret, tr0 + blink tr0, ZERO + + /* New syscall implementation*/ +system_call: + pta unknown_trap, tr0 + or r5, ZERO, r4 /* TRA (=r5) -> r4 */ + shlri r4, 20, r4 + bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */ + + /* It's a system call */ + st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */ + andi r5, 0x1ff, r5 /* syscall # -> r5 */ + + STI() + + pta syscall_allowed, tr0 + movi NR_syscalls - 1, r4 /* Last valid */ + bgeu/l r4, r5, tr0 + +syscall_bad: + /* Return ENOSYS ! */ + movi -(ENOSYS), r2 /* Fall-through */ + + .global syscall_ret +syscall_ret: + st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */ + +#ifdef CONFIG_POOR_MANS_STRACE + /* nothing useful in registers at this point */ + + movi evt_debug2, r5 + ori r5, 1, r5 + ptabs r5, tr0 + ld.q SP, FRAME_R(9), r2 + or SP, ZERO, r3 + blink tr0, LINK +#endif + + ld.q SP, FRAME_S(FSPC), r2 + addi r2, 4, r2 /* Move PC, being pre-execution event */ + st.q SP, FRAME_S(FSPC), r2 + pta ret_from_syscall, tr0 + blink tr0, ZERO + + +/* A different return path for ret_from_fork, because we now need + * to call schedule_tail with the later kernels. Because prev is + * loaded into r2 by switch_to() means we can just call it straight away + */ + +.global ret_from_fork +ret_from_fork: + + movi schedule_tail,r5 + ori r5, 1, r5 + ptabs r5, tr0 + blink tr0, LINK + +#ifdef CONFIG_POOR_MANS_STRACE + /* nothing useful in registers at this point */ + + movi evt_debug2, r5 + ori r5, 1, r5 + ptabs r5, tr0 + ld.q SP, FRAME_R(9), r2 + or SP, ZERO, r3 + blink tr0, LINK +#endif + + ld.q SP, FRAME_S(FSPC), r2 + addi r2, 4, r2 /* Move PC, being pre-execution event */ + st.q SP, FRAME_S(FSPC), r2 + pta ret_from_syscall, tr0 + blink tr0, ZERO + + + +syscall_allowed: + /* Use LINK to deflect the exit point, default is syscall_ret */ + pta syscall_ret, tr0 + gettr tr0, LINK + pta syscall_notrace, tr0 + + getcon KCR0, r2 + ld.l r2, TI_FLAGS, r4 + movi (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT), r6 + and r6, r4, r6 + beq/l r6, ZERO, tr0 + + /* Trace it by calling syscall_trace before and after */ + movi syscall_trace, r4 + or SP, ZERO, r2 + or ZERO, ZERO, r3 + ptabs r4, tr0 + blink tr0, LINK + + /* Reload syscall number as r5 is trashed by syscall_trace */ + ld.q SP, FRAME_S(FSYSCALL_ID), r5 + andi r5, 0x1ff, r5 + + pta syscall_ret_trace, tr0 + gettr tr0, LINK + +syscall_notrace: + /* Now point to the appropriate 4th level syscall handler */ + movi sys_call_table, r4 + shlli r5, 2, r5 + ldx.l r4, r5, r5 + ptabs r5, tr0 + + /* Prepare original args */ + ld.q SP, FRAME_R(2), r2 + ld.q SP, FRAME_R(3), r3 + ld.q SP, FRAME_R(4), r4 + ld.q SP, FRAME_R(5), r5 + ld.q SP, FRAME_R(6), r6 + ld.q SP, FRAME_R(7), r7 + + /* And now the trick for those syscalls requiring regs * ! */ + or SP, ZERO, r8 + + /* Call it */ + blink tr0, ZERO /* LINK is already properly set */ + +syscall_ret_trace: + /* We get back here only if under trace */ + st.q SP, FRAME_R(9), r2 /* Save return value */ + + movi syscall_trace, LINK + or SP, ZERO, r2 + movi 1, r3 + ptabs LINK, tr0 + blink tr0, LINK + + /* This needs to be done after any syscall tracing */ + ld.q SP, FRAME_S(FSPC), r2 + addi r2, 4, r2 /* Move PC, being pre-execution event */ + st.q SP, FRAME_S(FSPC), r2 + + pta ret_from_syscall, tr0 + blink tr0, ZERO /* Resume normal return sequence */ + +/* + * --- Switch to running under a particular ASID and return the previous ASID value + * --- The caller is assumed to have done a cli before calling this. + * + * Input r2 : new ASID + * Output r2 : old ASID + */ + + .global switch_and_save_asid +switch_and_save_asid: + getcon sr, r0 + movi 255, r4 + shlli r4, 16, r4 /* r4 = mask to select ASID */ + and r0, r4, r3 /* r3 = shifted old ASID */ + andi r2, 255, r2 /* mask down new ASID */ + shlli r2, 16, r2 /* align new ASID against SR.ASID */ + andc r0, r4, r0 /* efface old ASID from SR */ + or r0, r2, r0 /* insert the new ASID */ + putcon r0, ssr + movi 1f, r0 + putcon r0, spc + rte + nop +1: + ptabs LINK, tr0 + shlri r3, 16, r2 /* r2 = old ASID */ + blink tr0, r63 + + .global route_to_panic_handler +route_to_panic_handler: + /* Switch to real mode, goto panic_handler, don't return. Useful for + last-chance debugging, e.g. if no output wants to go to the console. + */ + + movi panic_handler - CONFIG_PAGE_OFFSET, r1 + ptabs r1, tr0 + pta 1f, tr1 + gettr tr1, r0 + putcon r0, spc + getcon sr, r0 + movi 1, r1 + shlli r1, 31, r1 + andc r0, r1, r0 + putcon r0, ssr + rte + nop +1: /* Now in real mode */ + blink tr0, r63 + nop + + .global peek_real_address_q +peek_real_address_q: + /* Two args: + r2 : real mode address to peek + r2(out) : result quadword + + This is provided as a cheapskate way of manipulating device + registers for debugging (to avoid the need to onchip_remap the debug + module, and to avoid the need to onchip_remap the watchpoint + controller in a way that identity maps sufficient bits to avoid the + SH5-101 cut2 silicon defect). + + This code is not performance critical + */ + + add.l r2, r63, r2 /* sign extend address */ + getcon sr, r0 /* r0 = saved original SR */ + movi 1, r1 + shlli r1, 28, r1 + or r0, r1, r1 /* r0 with block bit set */ + putcon r1, sr /* now in critical section */ + movi 1, r36 + shlli r36, 31, r36 + andc r1, r36, r1 /* turn sr.mmu off in real mode section */ + + putcon r1, ssr + movi .peek0 - CONFIG_PAGE_OFFSET, r36 /* real mode target address */ + movi 1f, r37 /* virtual mode return addr */ + putcon r36, spc + + synco + rte + nop + +.peek0: /* come here in real mode, don't touch caches!! + still in critical section (sr.bl==1) */ + putcon r0, ssr + putcon r37, spc + /* Here's the actual peek. If the address is bad, all bets are now off + * what will happen (handlers invoked in real-mode = bad news) */ + ld.q r2, 0, r2 + synco + rte /* Back to virtual mode */ + nop + +1: + ptabs LINK, tr0 + blink tr0, r63 + + .global poke_real_address_q +poke_real_address_q: + /* Two args: + r2 : real mode address to poke + r3 : quadword value to write. + + This is provided as a cheapskate way of manipulating device + registers for debugging (to avoid the need to onchip_remap the debug + module, and to avoid the need to onchip_remap the watchpoint + controller in a way that identity maps sufficient bits to avoid the + SH5-101 cut2 silicon defect). + + This code is not performance critical + */ + + add.l r2, r63, r2 /* sign extend address */ + getcon sr, r0 /* r0 = saved original SR */ + movi 1, r1 + shlli r1, 28, r1 + or r0, r1, r1 /* r0 with block bit set */ + putcon r1, sr /* now in critical section */ + movi 1, r36 + shlli r36, 31, r36 + andc r1, r36, r1 /* turn sr.mmu off in real mode section */ + + putcon r1, ssr + movi .poke0-CONFIG_PAGE_OFFSET, r36 /* real mode target address */ + movi 1f, r37 /* virtual mode return addr */ + putcon r36, spc + + synco + rte + nop + +.poke0: /* come here in real mode, don't touch caches!! + still in critical section (sr.bl==1) */ + putcon r0, ssr + putcon r37, spc + /* Here's the actual poke. If the address is bad, all bets are now off + * what will happen (handlers invoked in real-mode = bad news) */ + st.q r2, 0, r3 + synco + rte /* Back to virtual mode */ + nop + +1: + ptabs LINK, tr0 + blink tr0, r63 + +/* + * --- User Access Handling Section + */ + +/* + * User Access support. It all moved to non inlined Assembler + * functions in here. + * + * __kernel_size_t __copy_user(void *__to, const void *__from, + * __kernel_size_t __n) + * + * Inputs: + * (r2) target address + * (r3) source address + * (r4) size in bytes + * + * Ouputs: + * (*r2) target data + * (r2) non-copied bytes + * + * If a fault occurs on the user pointer, bail out early and return the + * number of bytes not copied in r2. + * Strategy : for large blocks, call a real memcpy function which can + * move >1 byte at a time using unaligned ld/st instructions, and can + * manipulate the cache using prefetch + alloco to improve the speed + * further. If a fault occurs in that function, just revert to the + * byte-by-byte approach used for small blocks; this is rare so the + * performance hit for that case does not matter. + * + * For small blocks it's not worth the overhead of setting up and calling + * the memcpy routine; do the copy a byte at a time. + * + */ + .global __copy_user +__copy_user: + pta __copy_user_byte_by_byte, tr1 + movi 16, r0 ! this value is a best guess, should tune it by benchmarking + bge/u r0, r4, tr1 + pta copy_user_memcpy, tr0 + addi SP, -32, SP + /* Save arguments in case we have to fix-up unhandled page fault */ + st.q SP, 0, r2 + st.q SP, 8, r3 + st.q SP, 16, r4 + st.q SP, 24, r35 ! r35 is callee-save + /* Save LINK in a register to reduce RTS time later (otherwise + ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */ + ori LINK, 0, r35 + blink tr0, LINK + + /* Copy completed normally if we get back here */ + ptabs r35, tr0 + ld.q SP, 24, r35 + /* don't restore r2-r4, pointless */ + /* set result=r2 to zero as the copy must have succeeded. */ + or r63, r63, r2 + addi SP, 32, SP + blink tr0, r63 ! RTS + + .global __copy_user_fixup +__copy_user_fixup: + /* Restore stack frame */ + ori r35, 0, LINK + ld.q SP, 24, r35 + ld.q SP, 16, r4 + ld.q SP, 8, r3 + ld.q SP, 0, r2 + addi SP, 32, SP + /* Fall through to original code, in the 'same' state we entered with */ + +/* The slow byte-by-byte method is used if the fast copy traps due to a bad + user address. In that rare case, the speed drop can be tolerated. */ +__copy_user_byte_by_byte: + pta ___copy_user_exit, tr1 + pta ___copy_user1, tr0 + beq/u r4, r63, tr1 /* early exit for zero length copy */ + sub r2, r3, r0 + addi r0, -1, r0 + +___copy_user1: + ld.b r3, 0, r5 /* Fault address 1 */ + + /* Could rewrite this to use just 1 add, but the second comes 'free' + due to load latency */ + addi r3, 1, r3 + addi r4, -1, r4 /* No real fixup required */ +___copy_user2: + stx.b r3, r0, r5 /* Fault address 2 */ + bne r4, ZERO, tr0 + +___copy_user_exit: + or r4, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * __kernel_size_t __clear_user(void *addr, __kernel_size_t size) + * + * Inputs: + * (r2) target address + * (r3) size in bytes + * + * Ouputs: + * (*r2) zero-ed target data + * (r2) non-zero-ed bytes + */ + .global __clear_user +__clear_user: + pta ___clear_user_exit, tr1 + pta ___clear_user1, tr0 + beq/u r3, r63, tr1 + +___clear_user1: + st.b r2, 0, ZERO /* Fault address */ + addi r2, 1, r2 + addi r3, -1, r3 /* No real fixup required */ + bne r3, ZERO, tr0 + +___clear_user_exit: + or r3, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + + +/* + * int __strncpy_from_user(unsigned long __dest, unsigned long __src, + * int __count) + * + * Inputs: + * (r2) target address + * (r3) source address + * (r4) maximum size in bytes + * + * Ouputs: + * (*r2) copied data + * (r2) -EFAULT (in case of faulting) + * copied data (otherwise) + */ + .global __strncpy_from_user +__strncpy_from_user: + pta ___strncpy_from_user1, tr0 + pta ___strncpy_from_user_done, tr1 + or r4, ZERO, r5 /* r5 = original count */ + beq/u r4, r63, tr1 /* early exit if r4==0 */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + +___strncpy_from_user1: + ld.b r3, 0, r7 /* Fault address: only in reading */ + st.b r2, 0, r7 + addi r2, 1, r2 + addi r3, 1, r3 + beq/u ZERO, r7, tr1 + addi r4, -1, r4 /* return real number of copied bytes */ + bne/l ZERO, r4, tr0 + +___strncpy_from_user_done: + sub r5, r4, r6 /* If done, return copied */ + +___strncpy_from_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * extern long __strnlen_user(const char *__s, long __n) + * + * Inputs: + * (r2) source address + * (r3) source size in bytes + * + * Ouputs: + * (r2) -EFAULT (in case of faulting) + * string length (otherwise) + */ + .global __strnlen_user +__strnlen_user: + pta ___strnlen_user_set_reply, tr0 + pta ___strnlen_user1, tr1 + or ZERO, ZERO, r5 /* r5 = counter */ + movi -(EFAULT), r6 /* r6 = reply, no real fixup */ + or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ + beq r3, ZERO, tr0 + +___strnlen_user1: + ldx.b r2, r5, r7 /* Fault address: only in reading */ + addi r3, -1, r3 /* No real fixup */ + addi r5, 1, r5 + beq r3, ZERO, tr0 + bne r7, ZERO, tr1 +! The line below used to be active. This meant led to a junk byte lying between each pair +! of entries in the argv & envp structures in memory. Whilst the program saw the right data +! via the argv and envp arguments to main, it meant the 'flat' representation visible through +! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. +! addi r5, 1, r5 /* Include '\0' */ + +___strnlen_user_set_reply: + or r5, ZERO, r6 /* If done, return counter */ + +___strnlen_user_exit: + or r6, ZERO, r2 + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * extern long __get_user_asm_?(void *val, long addr) + * + * Inputs: + * (r2) dest address + * (r3) source address (in User Space) + * + * Ouputs: + * (r2) -EFAULT (faulting) + * 0 (not faulting) + */ + .global __get_user_asm_b +__get_user_asm_b: + or r2, ZERO, r4 + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___get_user_asm_b1: + ld.b r3, 0, r5 /* r5 = data */ + st.b r4, 0, r5 + or ZERO, ZERO, r2 + +___get_user_asm_b_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __get_user_asm_w +__get_user_asm_w: + or r2, ZERO, r4 + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___get_user_asm_w1: + ld.w r3, 0, r5 /* r5 = data */ + st.w r4, 0, r5 + or ZERO, ZERO, r2 + +___get_user_asm_w_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __get_user_asm_l +__get_user_asm_l: + or r2, ZERO, r4 + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___get_user_asm_l1: + ld.l r3, 0, r5 /* r5 = data */ + st.l r4, 0, r5 + or ZERO, ZERO, r2 + +___get_user_asm_l_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __get_user_asm_q +__get_user_asm_q: + or r2, ZERO, r4 + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___get_user_asm_q1: + ld.q r3, 0, r5 /* r5 = data */ + st.q r4, 0, r5 + or ZERO, ZERO, r2 + +___get_user_asm_q_exit: + ptabs LINK, tr0 + blink tr0, ZERO + +/* + * extern long __put_user_asm_?(void *pval, long addr) + * + * Inputs: + * (r2) kernel pointer to value + * (r3) dest address (in User Space) + * + * Ouputs: + * (r2) -EFAULT (faulting) + * 0 (not faulting) + */ + .global __put_user_asm_b +__put_user_asm_b: + ld.b r2, 0, r4 /* r4 = data */ + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___put_user_asm_b1: + st.b r3, 0, r4 + or ZERO, ZERO, r2 + +___put_user_asm_b_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __put_user_asm_w +__put_user_asm_w: + ld.w r2, 0, r4 /* r4 = data */ + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___put_user_asm_w1: + st.w r3, 0, r4 + or ZERO, ZERO, r2 + +___put_user_asm_w_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __put_user_asm_l +__put_user_asm_l: + ld.l r2, 0, r4 /* r4 = data */ + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___put_user_asm_l1: + st.l r3, 0, r4 + or ZERO, ZERO, r2 + +___put_user_asm_l_exit: + ptabs LINK, tr0 + blink tr0, ZERO + + + .global __put_user_asm_q +__put_user_asm_q: + ld.q r2, 0, r4 /* r4 = data */ + movi -(EFAULT), r2 /* r2 = reply, no real fixup */ + +___put_user_asm_q1: + st.q r3, 0, r4 + or ZERO, ZERO, r2 + +___put_user_asm_q_exit: + ptabs LINK, tr0 + blink tr0, ZERO + +panic_stash_regs: + /* The idea is : when we get an unhandled panic, we dump the registers + to a known memory location, the just sit in a tight loop. + This allows the human to look at the memory region through the GDB + session (assuming the debug module's SHwy initiator isn't locked up + or anything), to hopefully analyze the cause of the panic. */ + + /* On entry, former r15 (SP) is in DCR + former r0 is at resvec_saved_area + 0 + former r1 is at resvec_saved_area + 8 + former tr0 is at resvec_saved_area + 32 + DCR is the only register whose value is lost altogether. + */ + + movi 0xffffffff80000000, r0 ! phy of dump area + ld.q SP, 0x000, r1 ! former r0 + st.q r0, 0x000, r1 + ld.q SP, 0x008, r1 ! former r1 + st.q r0, 0x008, r1 + st.q r0, 0x010, r2 + st.q r0, 0x018, r3 + st.q r0, 0x020, r4 + st.q r0, 0x028, r5 + st.q r0, 0x030, r6 + st.q r0, 0x038, r7 + st.q r0, 0x040, r8 + st.q r0, 0x048, r9 + st.q r0, 0x050, r10 + st.q r0, 0x058, r11 + st.q r0, 0x060, r12 + st.q r0, 0x068, r13 + st.q r0, 0x070, r14 + getcon dcr, r14 + st.q r0, 0x078, r14 + st.q r0, 0x080, r16 + st.q r0, 0x088, r17 + st.q r0, 0x090, r18 + st.q r0, 0x098, r19 + st.q r0, 0x0a0, r20 + st.q r0, 0x0a8, r21 + st.q r0, 0x0b0, r22 + st.q r0, 0x0b8, r23 + st.q r0, 0x0c0, r24 + st.q r0, 0x0c8, r25 + st.q r0, 0x0d0, r26 + st.q r0, 0x0d8, r27 + st.q r0, 0x0e0, r28 + st.q r0, 0x0e8, r29 + st.q r0, 0x0f0, r30 + st.q r0, 0x0f8, r31 + st.q r0, 0x100, r32 + st.q r0, 0x108, r33 + st.q r0, 0x110, r34 + st.q r0, 0x118, r35 + st.q r0, 0x120, r36 + st.q r0, 0x128, r37 + st.q r0, 0x130, r38 + st.q r0, 0x138, r39 + st.q r0, 0x140, r40 + st.q r0, 0x148, r41 + st.q r0, 0x150, r42 + st.q r0, 0x158, r43 + st.q r0, 0x160, r44 + st.q r0, 0x168, r45 + st.q r0, 0x170, r46 + st.q r0, 0x178, r47 + st.q r0, 0x180, r48 + st.q r0, 0x188, r49 + st.q r0, 0x190, r50 + st.q r0, 0x198, r51 + st.q r0, 0x1a0, r52 + st.q r0, 0x1a8, r53 + st.q r0, 0x1b0, r54 + st.q r0, 0x1b8, r55 + st.q r0, 0x1c0, r56 + st.q r0, 0x1c8, r57 + st.q r0, 0x1d0, r58 + st.q r0, 0x1d8, r59 + st.q r0, 0x1e0, r60 + st.q r0, 0x1e8, r61 + st.q r0, 0x1f0, r62 + st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake... + + ld.q SP, 0x020, r1 ! former tr0 + st.q r0, 0x200, r1 + gettr tr1, r1 + st.q r0, 0x208, r1 + gettr tr2, r1 + st.q r0, 0x210, r1 + gettr tr3, r1 + st.q r0, 0x218, r1 + gettr tr4, r1 + st.q r0, 0x220, r1 + gettr tr5, r1 + st.q r0, 0x228, r1 + gettr tr6, r1 + st.q r0, 0x230, r1 + gettr tr7, r1 + st.q r0, 0x238, r1 + + getcon sr, r1 + getcon ssr, r2 + getcon pssr, r3 + getcon spc, r4 + getcon pspc, r5 + getcon intevt, r6 + getcon expevt, r7 + getcon pexpevt, r8 + getcon tra, r9 + getcon tea, r10 + getcon kcr0, r11 + getcon kcr1, r12 + getcon vbr, r13 + getcon resvec, r14 + + st.q r0, 0x240, r1 + st.q r0, 0x248, r2 + st.q r0, 0x250, r3 + st.q r0, 0x258, r4 + st.q r0, 0x260, r5 + st.q r0, 0x268, r6 + st.q r0, 0x270, r7 + st.q r0, 0x278, r8 + st.q r0, 0x280, r9 + st.q r0, 0x288, r10 + st.q r0, 0x290, r11 + st.q r0, 0x298, r12 + st.q r0, 0x2a0, r13 + st.q r0, 0x2a8, r14 + + getcon SPC,r2 + getcon SSR,r3 + getcon EXPEVT,r4 + /* Prepare to jump to C - physical address */ + movi panic_handler-CONFIG_PAGE_OFFSET, r1 + ori r1, 1, r1 + ptabs r1, tr0 + getcon DCR, SP + blink tr0, ZERO + nop + nop + nop + nop + + + + +/* + * --- Signal Handling Section + */ + +/* + * extern long long _sa_default_rt_restorer + * extern long long _sa_default_restorer + * + * or, better, + * + * extern void _sa_default_rt_restorer(void) + * extern void _sa_default_restorer(void) + * + * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn() + * from user space. Copied into user space by signal management. + * Both must be quad aligned and 2 quad long (4 instructions). + * + */ + .balign 8 + .global sa_default_rt_restorer +sa_default_rt_restorer: + movi 0x10, r9 + shori __NR_rt_sigreturn, r9 + trapa r9 + nop + + .balign 8 + .global sa_default_restorer +sa_default_restorer: + movi 0x10, r9 + shori __NR_sigreturn, r9 + trapa r9 + nop + +/* + * --- __ex_table Section + */ + +/* + * User Access Exception Table. + */ + .section __ex_table, "a" + + .global asm_uaccess_start /* Just a marker */ +asm_uaccess_start: + + .long ___copy_user1, ___copy_user_exit + .long ___copy_user2, ___copy_user_exit + .long ___clear_user1, ___clear_user_exit + .long ___strncpy_from_user1, ___strncpy_from_user_exit + .long ___strnlen_user1, ___strnlen_user_exit + .long ___get_user_asm_b1, ___get_user_asm_b_exit + .long ___get_user_asm_w1, ___get_user_asm_w_exit + .long ___get_user_asm_l1, ___get_user_asm_l_exit + .long ___get_user_asm_q1, ___get_user_asm_q_exit + .long ___put_user_asm_b1, ___put_user_asm_b_exit + .long ___put_user_asm_w1, ___put_user_asm_w_exit + .long ___put_user_asm_l1, ___put_user_asm_l_exit + .long ___put_user_asm_q1, ___put_user_asm_q_exit + + .global asm_uaccess_end /* Just a marker */ +asm_uaccess_end: + + + + +/* + * --- .text.init Section + */ + + .section .text.init, "ax" + +/* + * void trap_init (void) + * + */ + .global trap_init +trap_init: + addi SP, -24, SP /* Room to save r28/r29/r30 */ + st.q SP, 0, r28 + st.q SP, 8, r29 + st.q SP, 16, r30 + + /* Set VBR and RESVEC */ + movi LVBR_block, r19 + andi r19, -4, r19 /* reset MMUOFF + reserved */ + /* For RESVEC exceptions we force the MMU off, which means we need the + physical address. */ + movi LRESVEC_block-CONFIG_PAGE_OFFSET, r20 + andi r20, -4, r20 /* reset reserved */ + ori r20, 1, r20 /* set MMUOFF */ + putcon r19, VBR + putcon r20, RESVEC + + /* Sanity check */ + movi LVBR_block_end, r21 + andi r21, -4, r21 + movi BLOCK_SIZE, r29 /* r29 = expected size */ + or r19, ZERO, r30 + add r19, r29, r19 + + /* + * Ugly, but better loop forever now than crash afterwards. + * We should print a message, but if we touch LVBR or + * LRESVEC blocks we should not be surprised if we get stuck + * in trap_init(). + */ + pta trap_init_loop, tr1 + gettr tr1, r28 /* r28 = trap_init_loop */ + sub r21, r30, r30 /* r30 = actual size */ + + /* + * VBR/RESVEC handlers overlap by being bigger than + * allowed. Very bad. Just loop forever. + * (r28) panic/loop address + * (r29) expected size + * (r30) actual size + */ +trap_init_loop: + bne r19, r21, tr1 + + /* Now that exception vectors are set up reset SR.BL */ + getcon SR, r22 + movi SR_UNBLOCK_EXC, r23 + and r22, r23, r22 + putcon r22, SR + + addi SP, 24, SP + ptabs LINK, tr0 + blink tr0, ZERO + diff -puN /dev/null arch/sh/kernel/cpu/sh5/fpu.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/fpu.c @@ -0,0 +1,166 @@ +/* + * arch/sh/kernel/cpu/sh5/fpu.c + * + * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli + * Copyright (C) 2002 STMicroelectronics Limited + * Author : Stuart Menefy + * + * Started from SH4 version: + * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +/* + * Initially load the FPU with signalling NANS. This bit pattern + * has the property that no matter whether considered as single or as + * double precision, it still represents a signalling NAN. + */ +#define sNAN64 0xFFFFFFFFFFFFFFFFULL +#define sNAN32 0xFFFFFFFFUL + +static union sh_fpu_union init_fpuregs = { + .hard = { + .fp_regs = { [0 ... 63] = sNAN32 }, + .fpscr = FPSCR_INIT + } +}; + +void save_fpu(struct task_struct *tsk, struct pt_regs *regs) +{ + asm volatile("fst.p %0, (0*8), fp0\n\t" + "fst.p %0, (1*8), fp2\n\t" + "fst.p %0, (2*8), fp4\n\t" + "fst.p %0, (3*8), fp6\n\t" + "fst.p %0, (4*8), fp8\n\t" + "fst.p %0, (5*8), fp10\n\t" + "fst.p %0, (6*8), fp12\n\t" + "fst.p %0, (7*8), fp14\n\t" + "fst.p %0, (8*8), fp16\n\t" + "fst.p %0, (9*8), fp18\n\t" + "fst.p %0, (10*8), fp20\n\t" + "fst.p %0, (11*8), fp22\n\t" + "fst.p %0, (12*8), fp24\n\t" + "fst.p %0, (13*8), fp26\n\t" + "fst.p %0, (14*8), fp28\n\t" + "fst.p %0, (15*8), fp30\n\t" + "fst.p %0, (16*8), fp32\n\t" + "fst.p %0, (17*8), fp34\n\t" + "fst.p %0, (18*8), fp36\n\t" + "fst.p %0, (19*8), fp38\n\t" + "fst.p %0, (20*8), fp40\n\t" + "fst.p %0, (21*8), fp42\n\t" + "fst.p %0, (22*8), fp44\n\t" + "fst.p %0, (23*8), fp46\n\t" + "fst.p %0, (24*8), fp48\n\t" + "fst.p %0, (25*8), fp50\n\t" + "fst.p %0, (26*8), fp52\n\t" + "fst.p %0, (27*8), fp54\n\t" + "fst.p %0, (28*8), fp56\n\t" + "fst.p %0, (29*8), fp58\n\t" + "fst.p %0, (30*8), fp60\n\t" + "fst.p %0, (31*8), fp62\n\t" + + "fgetscr fr63\n\t" + "fst.s %0, (32*8), fr63\n\t" + : /* no output */ + : "r" (&tsk->thread.fpu.hard) + : "memory"); +} + +static inline void +fpload(struct sh_fpu_hard_struct *fpregs) +{ + asm volatile("fld.p %0, (0*8), fp0\n\t" + "fld.p %0, (1*8), fp2\n\t" + "fld.p %0, (2*8), fp4\n\t" + "fld.p %0, (3*8), fp6\n\t" + "fld.p %0, (4*8), fp8\n\t" + "fld.p %0, (5*8), fp10\n\t" + "fld.p %0, (6*8), fp12\n\t" + "fld.p %0, (7*8), fp14\n\t" + "fld.p %0, (8*8), fp16\n\t" + "fld.p %0, (9*8), fp18\n\t" + "fld.p %0, (10*8), fp20\n\t" + "fld.p %0, (11*8), fp22\n\t" + "fld.p %0, (12*8), fp24\n\t" + "fld.p %0, (13*8), fp26\n\t" + "fld.p %0, (14*8), fp28\n\t" + "fld.p %0, (15*8), fp30\n\t" + "fld.p %0, (16*8), fp32\n\t" + "fld.p %0, (17*8), fp34\n\t" + "fld.p %0, (18*8), fp36\n\t" + "fld.p %0, (19*8), fp38\n\t" + "fld.p %0, (20*8), fp40\n\t" + "fld.p %0, (21*8), fp42\n\t" + "fld.p %0, (22*8), fp44\n\t" + "fld.p %0, (23*8), fp46\n\t" + "fld.p %0, (24*8), fp48\n\t" + "fld.p %0, (25*8), fp50\n\t" + "fld.p %0, (26*8), fp52\n\t" + "fld.p %0, (27*8), fp54\n\t" + "fld.p %0, (28*8), fp56\n\t" + "fld.p %0, (29*8), fp58\n\t" + "fld.p %0, (30*8), fp60\n\t" + + "fld.s %0, (32*8), fr63\n\t" + "fputscr fr63\n\t" + + "fld.p %0, (31*8), fp62\n\t" + : /* no output */ + : "r" (fpregs) ); +} + +void fpinit(struct sh_fpu_hard_struct *fpregs) +{ + *fpregs = init_fpuregs.hard; +} + +asmlinkage void +do_fpu_error(unsigned long ex, struct pt_regs *regs) +{ + struct task_struct *tsk = current; + + regs->pc += 4; + + tsk->thread.trap_no = 11; + tsk->thread.error_code = 0; + force_sig(SIGFPE, tsk); +} + + +asmlinkage void +do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) +{ + void die(const char *str, struct pt_regs *regs, long err); + + if (! user_mode(regs)) + die("FPU used in kernel", regs, ex); + + regs->sr &= ~SR_FD; + + if (last_task_used_math == current) + return; + + enable_fpu(); + if (last_task_used_math != NULL) + /* Other processes fpu state, save away */ + save_fpu(last_task_used_math, regs); + + last_task_used_math = current; + if (used_math()) { + fpload(¤t->thread.fpu.hard); + } else { + /* First time FPU user. */ + fpload(&init_fpuregs.hard); + set_used_math(); + } + disable_fpu(); +} diff -puN /dev/null arch/sh/kernel/cpu/sh5/probe.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/probe.c @@ -0,0 +1,76 @@ +/* + * arch/sh/kernel/cpu/sh5/probe.c + * + * CPU Subtype Probing for SH-5. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +int __init detect_cpu_and_cache_system(void) +{ + unsigned long long cir; + + /* Do peeks in real mode to avoid having to set up a mapping for the + WPC registers. On SH5-101 cut2, such a mapping would be exposed to + an address translation erratum which would make it hard to set up + correctly. */ + cir = peek_real_address_q(0x0d000008); + if ((cir & 0xffff) == 0x5103) { + boot_cpu_data.type = CPU_SH5_103; + } else if (((cir >> 32) & 0xffff) == 0x51e2) { + /* CPU.VCR aliased at CIR address on SH5-101 */ + boot_cpu_data.type = CPU_SH5_101; + } else { + boot_cpu_data.type = CPU_SH_NONE; + } + + /* + * First, setup some sane values for the I-cache. + */ + boot_cpu_data.icache.ways = 4; + boot_cpu_data.icache.sets = 256; + boot_cpu_data.icache.linesz = L1_CACHE_BYTES; + +#if 0 + /* + * FIXME: This can probably be cleaned up a bit as well.. for example, + * do we really need the way shift _and_ the way_step_shift ?? Judging + * by the existing code, I would guess no.. is there any valid reason + * why we need to be tracking this around? + */ + boot_cpu_data.icache.way_shift = 13; + boot_cpu_data.icache.entry_shift = 5; + boot_cpu_data.icache.set_shift = 4; + boot_cpu_data.icache.way_step_shift = 16; + boot_cpu_data.icache.asid_shift = 2; + + /* + * way offset = cache size / associativity, so just don't factor in + * associativity in the first place.. + */ + boot_cpu_data.icache.way_ofs = boot_cpu_data.icache.sets * + boot_cpu_data.icache.linesz; + + boot_cpu_data.icache.asid_mask = 0x3fc; + boot_cpu_data.icache.idx_mask = 0x1fe0; + boot_cpu_data.icache.epn_mask = 0xffffe000; +#endif + + boot_cpu_data.icache.flags = 0; + + /* A trivial starting point.. */ + memcpy(&boot_cpu_data.dcache, + &boot_cpu_data.icache, sizeof(struct cache_info)); + + return 0; +} diff -puN /dev/null arch/sh/kernel/cpu/sh5/switchto.S --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/switchto.S @@ -0,0 +1,198 @@ +/* + * arch/sh/kernel/cpu/sh5/switchto.S + * + * sh64 context switch + * + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. +*/ + + .section .text..SHmedia32,"ax" + .little + + .balign 32 + + .type sh64_switch_to,@function + .global sh64_switch_to + .global __sh64_switch_to_end +sh64_switch_to: + +/* Incoming args + r2 - prev + r3 - &prev->thread + r4 - next + r5 - &next->thread + + Outgoing results + r2 - last (=prev) : this just stays in r2 throughout + + Want to create a full (struct pt_regs) on the stack to allow backtracing + functions to work. However, we only need to populate the callee-save + register slots in this structure; since we're a function our ancestors must + have themselves preserved all caller saved state in the stack. This saves + some wasted effort since we won't need to look at the values. + + In particular, all caller-save registers are immediately available for + scratch use. + +*/ + +#define FRAME_SIZE (76*8 + 8) + + movi FRAME_SIZE, r0 + sub.l r15, r0, r15 + ! Do normal-style register save to support backtrace + + st.l r15, 0, r18 ! save link reg + st.l r15, 4, r14 ! save fp + add.l r15, r63, r14 ! setup frame pointer + + ! hopefully this looks normal to the backtrace now. + + addi.l r15, 8, r1 ! base of pt_regs + addi.l r1, 24, r0 ! base of pt_regs.regs + addi.l r0, (63*8), r8 ! base of pt_regs.trregs + + /* Note : to be fixed? + struct pt_regs is really designed for holding the state on entry + to an exception, i.e. pc,sr,regs etc. However, for the context + switch state, some of this is not required. But the unwinder takes + struct pt_regs * as an arg so we have to build this structure + to allow unwinding switched tasks in show_state() */ + + st.q r0, ( 9*8), r9 + st.q r0, (10*8), r10 + st.q r0, (11*8), r11 + st.q r0, (12*8), r12 + st.q r0, (13*8), r13 + st.q r0, (14*8), r14 ! for unwind, want to look as though we took a trap at + ! the point where the process is left in suspended animation, i.e. current + ! fp here, not the saved one. + st.q r0, (16*8), r16 + + st.q r0, (24*8), r24 + st.q r0, (25*8), r25 + st.q r0, (26*8), r26 + st.q r0, (27*8), r27 + st.q r0, (28*8), r28 + st.q r0, (29*8), r29 + st.q r0, (30*8), r30 + st.q r0, (31*8), r31 + st.q r0, (32*8), r32 + st.q r0, (33*8), r33 + st.q r0, (34*8), r34 + st.q r0, (35*8), r35 + + st.q r0, (44*8), r44 + st.q r0, (45*8), r45 + st.q r0, (46*8), r46 + st.q r0, (47*8), r47 + st.q r0, (48*8), r48 + st.q r0, (49*8), r49 + st.q r0, (50*8), r50 + st.q r0, (51*8), r51 + st.q r0, (52*8), r52 + st.q r0, (53*8), r53 + st.q r0, (54*8), r54 + st.q r0, (55*8), r55 + st.q r0, (56*8), r56 + st.q r0, (57*8), r57 + st.q r0, (58*8), r58 + st.q r0, (59*8), r59 + + ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency) + ! Use a local label to avoid creating a symbol that will confuse the ! + ! backtrace + pta .Lsave_pc, tr0 + + gettr tr5, r45 + gettr tr6, r46 + gettr tr7, r47 + st.q r8, (5*8), r45 + st.q r8, (6*8), r46 + st.q r8, (7*8), r47 + + ! Now switch context + gettr tr0, r9 + st.l r3, 0, r15 ! prev->thread.sp + st.l r3, 8, r1 ! prev->thread.kregs + st.l r3, 4, r9 ! prev->thread.pc + st.q r1, 0, r9 ! save prev->thread.pc into pt_regs->pc + + ! Load PC for next task (init value or save_pc later) + ld.l r5, 4, r18 ! next->thread.pc + ! Switch stacks + ld.l r5, 0, r15 ! next->thread.sp + ptabs r18, tr0 + + ! Update current + ld.l r4, 4, r9 ! next->thread_info (2nd element of next task_struct) + putcon r9, kcr0 ! current = next->thread_info + + ! go to save_pc for a reschedule, or the initial thread.pc for a new process + blink tr0, r63 + + ! Restore (when we come back to a previously saved task) +.Lsave_pc: + addi.l r15, 32, r0 ! r0 = next's regs + addi.l r0, (63*8), r8 ! r8 = next's tr_regs + + ld.q r8, (5*8), r45 + ld.q r8, (6*8), r46 + ld.q r8, (7*8), r47 + ptabs r45, tr5 + ptabs r46, tr6 + ptabs r47, tr7 + + ld.q r0, ( 9*8), r9 + ld.q r0, (10*8), r10 + ld.q r0, (11*8), r11 + ld.q r0, (12*8), r12 + ld.q r0, (13*8), r13 + ld.q r0, (14*8), r14 + ld.q r0, (16*8), r16 + + ld.q r0, (24*8), r24 + ld.q r0, (25*8), r25 + ld.q r0, (26*8), r26 + ld.q r0, (27*8), r27 + ld.q r0, (28*8), r28 + ld.q r0, (29*8), r29 + ld.q r0, (30*8), r30 + ld.q r0, (31*8), r31 + ld.q r0, (32*8), r32 + ld.q r0, (33*8), r33 + ld.q r0, (34*8), r34 + ld.q r0, (35*8), r35 + + ld.q r0, (44*8), r44 + ld.q r0, (45*8), r45 + ld.q r0, (46*8), r46 + ld.q r0, (47*8), r47 + ld.q r0, (48*8), r48 + ld.q r0, (49*8), r49 + ld.q r0, (50*8), r50 + ld.q r0, (51*8), r51 + ld.q r0, (52*8), r52 + ld.q r0, (53*8), r53 + ld.q r0, (54*8), r54 + ld.q r0, (55*8), r55 + ld.q r0, (56*8), r56 + ld.q r0, (57*8), r57 + ld.q r0, (58*8), r58 + ld.q r0, (59*8), r59 + + ! epilogue + ld.l r15, 0, r18 + ld.l r15, 4, r14 + ptabs r18, tr0 + movi FRAME_SIZE, r0 + add r15, r0, r15 + blink tr0, r63 +__sh64_switch_to_end: +.LFE1: + .size sh64_switch_to,.LFE1-sh64_switch_to + diff -puN /dev/null arch/sh/kernel/cpu/sh5/unwind.c --- /dev/null +++ a/arch/sh/kernel/cpu/sh5/unwind.c @@ -0,0 +1,326 @@ +/* + * arch/sh/kernel/cpu/sh5/unwind.c + * + * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +static u8 regcache[63]; + +/* + * Finding the previous stack frame isn't horribly straightforward as it is + * on some other platforms. In the sh64 case, we don't have "linked" stack + * frames, so we need to do a bit of work to determine the previous frame, + * and in turn, the previous r14/r18 pair. + * + * There are generally a few cases which determine where we can find out + * the r14/r18 values. In the general case, this can be determined by poking + * around the prologue of the symbol PC is in (note that we absolutely must + * have frame pointer support as well as the kernel symbol table mapped, + * otherwise we can't even get this far). + * + * In other cases, such as the interrupt/exception path, we can poke around + * the sp/fp. + * + * Notably, this entire approach is somewhat error prone, and in the event + * that the previous frame cannot be determined, that's all we can do. + * Either way, this still leaves us with a more correct backtrace then what + * we would be able to come up with by walking the stack (which is garbage + * for anything beyond the first frame). + * -- PFM. + */ +static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, + unsigned long *pprev_fp, unsigned long *pprev_pc, + struct pt_regs *regs) +{ + const char *sym; + char namebuf[128]; + unsigned long offset; + unsigned long prologue = 0; + unsigned long fp_displacement = 0; + unsigned long fp_prev = 0; + unsigned long offset_r14 = 0, offset_r18 = 0; + int i, found_prologue_end = 0; + + sym = kallsyms_lookup(pc, NULL, &offset, NULL, namebuf); + if (!sym) + return -EINVAL; + + prologue = pc - offset; + if (!prologue) + return -EINVAL; + + /* Validate fp, to avoid risk of dereferencing a bad pointer later. + Assume 128Mb since that's the amount of RAM on a Cayman. Modify + when there is an SH-5 board with more. */ + if ((fp < (unsigned long) phys_to_virt(__MEMORY_START)) || + (fp >= (unsigned long)(phys_to_virt(__MEMORY_START)) + 128*1024*1024) || + ((fp & 7) != 0)) { + return -EINVAL; + } + + /* + * Depth to walk, depth is completely arbitrary. + */ + for (i = 0; i < 100; i++, prologue += sizeof(unsigned long)) { + unsigned long op; + u8 major, minor; + u8 src, dest, disp; + + op = *(unsigned long *)prologue; + + major = (op >> 26) & 0x3f; + src = (op >> 20) & 0x3f; + minor = (op >> 16) & 0xf; + disp = (op >> 10) & 0x3f; + dest = (op >> 4) & 0x3f; + + /* + * Stack frame creation happens in a number of ways.. in the + * general case when the stack frame is less than 511 bytes, + * it's generally created by an addi or addi.l: + * + * addi/addi.l r15, -FRAME_SIZE, r15 + * + * in the event that the frame size is bigger than this, it's + * typically created using a movi/sub pair as follows: + * + * movi FRAME_SIZE, rX + * sub r15, rX, r15 + */ + + switch (major) { + case (0x00 >> 2): + switch (minor) { + case 0x8: /* add.l */ + case 0x9: /* add */ + /* Look for r15, r63, r14 */ + if (src == 15 && disp == 63 && dest == 14) + found_prologue_end = 1; + + break; + case 0xa: /* sub.l */ + case 0xb: /* sub */ + if (src != 15 || dest != 15) + continue; + + fp_displacement -= regcache[disp]; + fp_prev = fp - fp_displacement; + break; + } + break; + case (0xa8 >> 2): /* st.l */ + if (src != 15) + continue; + + switch (dest) { + case 14: + if (offset_r14 || fp_displacement == 0) + continue; + + offset_r14 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); + offset_r14 *= sizeof(unsigned long); + offset_r14 += fp_displacement; + break; + case 18: + if (offset_r18 || fp_displacement == 0) + continue; + + offset_r18 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); + offset_r18 *= sizeof(unsigned long); + offset_r18 += fp_displacement; + break; + } + + break; + case (0xcc >> 2): /* movi */ + if (dest >= 63) { + printk(KERN_NOTICE "%s: Invalid dest reg %d " + "specified in movi handler. Failed " + "opcode was 0x%lx: ", __FUNCTION__, + dest, op); + + continue; + } + + /* Sign extend */ + regcache[dest] = + ((((s64)(u64)op >> 10) & 0xffff) << 54) >> 54; + break; + case (0xd0 >> 2): /* addi */ + case (0xd4 >> 2): /* addi.l */ + /* Look for r15, -FRAME_SIZE, r15 */ + if (src != 15 || dest != 15) + continue; + + /* Sign extended frame size.. */ + fp_displacement += + (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); + fp_prev = fp - fp_displacement; + break; + } + + if (found_prologue_end && offset_r14 && (offset_r18 || *pprev_pc) && fp_prev) + break; + } + + if (offset_r14 == 0 || fp_prev == 0) { + if (!offset_r14) + pr_debug("Unable to find r14 offset\n"); + if (!fp_prev) + pr_debug("Unable to find previous fp\n"); + + return -EINVAL; + } + + /* For innermost leaf function, there might not be a offset_r18 */ + if (!*pprev_pc && (offset_r18 == 0)) + return -EINVAL; + + *pprev_fp = *(unsigned long *)(fp_prev + offset_r14); + + if (offset_r18) + *pprev_pc = *(unsigned long *)(fp_prev + offset_r18); + + *pprev_pc &= ~1; + + return 0; +} + +/* Don't put this on the stack since we'll want to call sh64_unwind + * when we're close to underflowing the stack anyway. */ +static struct pt_regs here_regs; + +extern const char syscall_ret; +extern const char ret_from_syscall; +extern const char ret_from_exception; +extern const char ret_from_irq; + +static void sh64_unwind_inner(struct pt_regs *regs); + +static void unwind_nested (unsigned long pc, unsigned long fp) +{ + if ((fp >= __MEMORY_START) && + ((fp & 7) == 0)) { + sh64_unwind_inner((struct pt_regs *) fp); + } +} + +static void sh64_unwind_inner(struct pt_regs *regs) +{ + unsigned long pc, fp; + int ofs = 0; + int first_pass; + + pc = regs->pc & ~1; + fp = regs->regs[14]; + + first_pass = 1; + for (;;) { + int cond; + unsigned long next_fp, next_pc; + + if (pc == ((unsigned long) &syscall_ret & ~1)) { + printk("SYSCALL\n"); + unwind_nested(pc,fp); + return; + } + + if (pc == ((unsigned long) &ret_from_syscall & ~1)) { + printk("SYSCALL (PREEMPTED)\n"); + unwind_nested(pc,fp); + return; + } + + /* In this case, the PC is discovered by lookup_prev_stack_frame but + it has 4 taken off it to look like the 'caller' */ + if (pc == ((unsigned long) &ret_from_exception & ~1)) { + printk("EXCEPTION\n"); + unwind_nested(pc,fp); + return; + } + + if (pc == ((unsigned long) &ret_from_irq & ~1)) { + printk("IRQ\n"); + unwind_nested(pc,fp); + return; + } + + cond = ((pc >= __MEMORY_START) && (fp >= __MEMORY_START) && + ((pc & 3) == 0) && ((fp & 7) == 0)); + + pc -= ofs; + + printk("[<%08lx>] ", pc); + print_symbol("%s\n", pc); + + if (first_pass) { + /* If the innermost frame is a leaf function, it's + * possible that r18 is never saved out to the stack. + */ + next_pc = regs->regs[18]; + } else { + next_pc = 0; + } + + if (lookup_prev_stack_frame(fp, pc, &next_fp, &next_pc, regs) == 0) { + ofs = sizeof(unsigned long); + pc = next_pc & ~1; + fp = next_fp; + } else { + printk("Unable to lookup previous stack frame\n"); + break; + } + first_pass = 0; + } + + printk("\n"); + +} + +void sh64_unwind(struct pt_regs *regs) +{ + if (!regs) { + /* + * Fetch current regs if we have no other saved state to back + * trace from. + */ + regs = &here_regs; + + __asm__ __volatile__ ("ori r14, 0, %0" : "=r" (regs->regs[14])); + __asm__ __volatile__ ("ori r15, 0, %0" : "=r" (regs->regs[15])); + __asm__ __volatile__ ("ori r18, 0, %0" : "=r" (regs->regs[18])); + + __asm__ __volatile__ ("gettr tr0, %0" : "=r" (regs->tregs[0])); + __asm__ __volatile__ ("gettr tr1, %0" : "=r" (regs->tregs[1])); + __asm__ __volatile__ ("gettr tr2, %0" : "=r" (regs->tregs[2])); + __asm__ __volatile__ ("gettr tr3, %0" : "=r" (regs->tregs[3])); + __asm__ __volatile__ ("gettr tr4, %0" : "=r" (regs->tregs[4])); + __asm__ __volatile__ ("gettr tr5, %0" : "=r" (regs->tregs[5])); + __asm__ __volatile__ ("gettr tr6, %0" : "=r" (regs->tregs[6])); + __asm__ __volatile__ ("gettr tr7, %0" : "=r" (regs->tregs[7])); + + __asm__ __volatile__ ( + "pta 0f, tr0\n\t" + "blink tr0, %0\n\t" + "0: nop" + : "=r" (regs->pc) + ); + } + + printk("\nCall Trace:\n"); + sh64_unwind_inner(regs); +} + diff -puN /dev/null arch/sh/kernel/dump_task.c --- /dev/null +++ a/arch/sh/kernel/dump_task.c @@ -0,0 +1,31 @@ +#include +#include + +/* + * Capture the user space registers if the task is not running (in user space) + */ +int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) +{ + struct pt_regs ptregs; + + ptregs = *task_pt_regs(tsk); + elf_core_copy_regs(regs, &ptregs); + + return 1; +} + +int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu) +{ + int fpvalid = 0; + +#if defined(CONFIG_SH_FPU) + fpvalid = !!tsk_used_math(tsk); + if (fpvalid) { + unlazy_fpu(tsk, task_pt_regs(tsk)); + memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); + } +#endif + + return fpvalid; +} + diff -puN arch/sh/kernel/entry-common.S~git-sh arch/sh/kernel/entry-common.S --- a/arch/sh/kernel/entry-common.S~git-sh +++ a/arch/sh/kernel/entry-common.S @@ -176,25 +176,6 @@ work_notifysig: jmp @r1 lds r0, pr work_resched: -#if defined(CONFIG_GUSA) && !defined(CONFIG_PREEMPT) - ! gUSA handling - mov.l @(OFF_SP,r15), r0 ! get user space stack pointer - mov r0, r1 - shll r0 - bf/s 1f - shll r0 - bf/s 1f - mov #OFF_PC, r0 - ! SP >= 0xc0000000 : gUSA mark - mov.l @(r0,r15), r2 ! get user space PC (program counter) - mov.l @(OFF_R0,r15), r3 ! end point - cmp/hs r3, r2 ! r2 >= r3? - bt 1f - add r3, r1 ! rewind point #2 - mov.l r1, @(r0,r15) ! reset PC to rewind point #2 - ! -1: -#endif mov.l 1f, r1 jsr @r1 ! schedule nop @@ -224,7 +205,7 @@ work_resched: syscall_exit_work: ! r0: current_thread_info->flags ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP, r0 + tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 #ifdef CONFIG_TRACE_IRQFLAGS @@ -234,6 +215,8 @@ syscall_exit_work: #endif sti ! XXX setup arguments... + mov r15, r4 + mov #1, r5 mov.l 4f, r0 ! do_syscall_trace jsr @r0 nop @@ -244,6 +227,8 @@ syscall_exit_work: syscall_trace_entry: ! Yes it is traced. ! XXX setup arguments... + mov r15, r4 + mov #0, r5 mov.l 4f, r11 ! Call do_syscall_trace which notifies jsr @r11 ! superior (will chomp R[0-7]) nop @@ -366,7 +351,7 @@ ENTRY(system_call) ! get_current_thread_info r8, r10 mov.l @(TI_FLAGS,r8), r8 - mov #_TIF_SYSCALL_TRACE, r10 + mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10 tst r10, r8 bf syscall_trace_entry ! diff -puN arch/sh/kernel/head.S~git-sh /dev/null --- a/arch/sh/kernel/head.S +++ /dev/null @@ -1,120 +0,0 @@ -/* $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $ - * - * arch/sh/kernel/head.S - * - * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Head.S contains the SH exception handlers and startup code. - */ -#include -#include - -#ifdef CONFIG_CPU_SH4A -#define SYNCO() synco - -#define PREFI(label, reg) \ - mov.l label, reg; \ - prefi @reg -#else -#define SYNCO() -#define PREFI(label, reg) -#endif - - .section .empty_zero_page, "aw" -ENTRY(empty_zero_page) - .long 1 /* MOUNT_ROOT_RDONLY */ - .long 0 /* RAMDISK_FLAGS */ - .long 0x0200 /* ORIG_ROOT_DEV */ - .long 1 /* LOADER_TYPE */ - .long 0x00360000 /* INITRD_START */ - .long 0x000a0000 /* INITRD_SIZE */ - .long 0 -1: - .skip PAGE_SIZE - empty_zero_page - 1b - - .section .text.head, "ax" - -/* - * Condition at the entry of _stext: - * - * BSC has already been initialized. - * INTC may or may not be initialized. - * VBR may or may not be initialized. - * MMU may or may not be initialized. - * Cache may or may not be initialized. - * Hardware (including on-chip modules) may or may not be initialized. - * - */ -ENTRY(_stext) - ! Initialize Status Register - mov.l 1f, r0 ! MD=1, RB=0, BL=0, IMASK=0xF - ldc r0, sr - ! Initialize global interrupt mask -#ifdef CONFIG_CPU_HAS_SR_RB - mov #0, r0 - ldc r0, r6_bank -#endif - - /* - * Prefetch if possible to reduce cache miss penalty. - * - * We do this early on for SH-4A as a micro-optimization, - * as later on we will have speculative execution enabled - * and this will become less of an issue. - */ - PREFI(5f, r0) - PREFI(6f, r0) - - ! - mov.l 2f, r0 - mov r0, r15 ! Set initial r15 (stack pointer) -#ifdef CONFIG_CPU_HAS_SR_RB - mov.l 7f, r0 - ldc r0, r7_bank ! ... and initial thread_info -#endif - - ! Clear BSS area -#ifdef CONFIG_SMP - mov.l 3f, r0 - cmp/eq #0, r0 ! skip clear if set to zero - bt 10f -#endif - - mov.l 3f, r1 - add #4, r1 - mov.l 4f, r2 - mov #0, r0 -9: cmp/hs r2, r1 - bf/s 9b ! while (r1 < r2) - mov.l r0,@-r2 - -10: - ! Additional CPU initialization - mov.l 6f, r0 - jsr @r0 - nop - - SYNCO() ! Wait for pending instructions.. - - ! Start kernel - mov.l 5f, r0 - jmp @r0 - nop - - .balign 4 -#if defined(CONFIG_CPU_SH2) -1: .long 0x000000F0 ! IMASK=0xF -#else -1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF -#endif -ENTRY(stack_start) -2: .long init_thread_union+THREAD_SIZE -3: .long __bss_start -4: .long _end -5: .long start_kernel -6: .long sh_cpu_init -7: .long init_thread_union diff -puN /dev/null arch/sh/kernel/head_32.S --- /dev/null +++ a/arch/sh/kernel/head_32.S @@ -0,0 +1,124 @@ +/* $Id: head.S,v 1.7 2003/09/01 17:58:19 lethal Exp $ + * + * arch/sh/kernel/head.S + * + * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Head.S contains the SH exception handlers and startup code. + */ +#include +#include + +#ifdef CONFIG_CPU_SH4A +#define SYNCO() synco + +#define PREFI(label, reg) \ + mov.l label, reg; \ + prefi @reg +#else +#define SYNCO() +#define PREFI(label, reg) +#endif + + .section .empty_zero_page, "aw" +ENTRY(empty_zero_page) + .long 1 /* MOUNT_ROOT_RDONLY */ + .long 0 /* RAMDISK_FLAGS */ + .long 0x0200 /* ORIG_ROOT_DEV */ + .long 1 /* LOADER_TYPE */ + .long 0x00360000 /* INITRD_START */ + .long 0x000a0000 /* INITRD_SIZE */ +#ifdef CONFIG_32BIT + .long 0x53453f00 + 32 /* "SE?" = 32 bit */ +#else + .long 0x53453f00 + 29 /* "SE?" = 29 bit */ +#endif +1: + .skip PAGE_SIZE - empty_zero_page - 1b + + .section .text.head, "ax" + +/* + * Condition at the entry of _stext: + * + * BSC has already been initialized. + * INTC may or may not be initialized. + * VBR may or may not be initialized. + * MMU may or may not be initialized. + * Cache may or may not be initialized. + * Hardware (including on-chip modules) may or may not be initialized. + * + */ +ENTRY(_stext) + ! Initialize Status Register + mov.l 1f, r0 ! MD=1, RB=0, BL=0, IMASK=0xF + ldc r0, sr + ! Initialize global interrupt mask +#ifdef CONFIG_CPU_HAS_SR_RB + mov #0, r0 + ldc r0, r6_bank +#endif + + /* + * Prefetch if possible to reduce cache miss penalty. + * + * We do this early on for SH-4A as a micro-optimization, + * as later on we will have speculative execution enabled + * and this will become less of an issue. + */ + PREFI(5f, r0) + PREFI(6f, r0) + + ! + mov.l 2f, r0 + mov r0, r15 ! Set initial r15 (stack pointer) +#ifdef CONFIG_CPU_HAS_SR_RB + mov.l 7f, r0 + ldc r0, r7_bank ! ... and initial thread_info +#endif + + ! Clear BSS area +#ifdef CONFIG_SMP + mov.l 3f, r0 + cmp/eq #0, r0 ! skip clear if set to zero + bt 10f +#endif + + mov.l 3f, r1 + add #4, r1 + mov.l 4f, r2 + mov #0, r0 +9: cmp/hs r2, r1 + bf/s 9b ! while (r1 < r2) + mov.l r0,@-r2 + +10: + ! Additional CPU initialization + mov.l 6f, r0 + jsr @r0 + nop + + SYNCO() ! Wait for pending instructions.. + + ! Start kernel + mov.l 5f, r0 + jmp @r0 + nop + + .balign 4 +#if defined(CONFIG_CPU_SH2) +1: .long 0x000000F0 ! IMASK=0xF +#else +1: .long 0x400080F0 ! MD=1, RB=0, BL=0, FD=1, IMASK=0xF +#endif +ENTRY(stack_start) +2: .long init_thread_union+THREAD_SIZE +3: .long __bss_start +4: .long _end +5: .long start_kernel +6: .long sh_cpu_init +7: .long init_thread_union diff -puN /dev/null arch/sh/kernel/head_64.S --- /dev/null +++ a/arch/sh/kernel/head_64.S @@ -0,0 +1,356 @@ +/* + * arch/sh/kernel/head_64.S + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include + +/* + * MMU defines: TLB boundaries. + */ + +#define MMUIR_FIRST ITLB_FIXED +#define MMUIR_END ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP +#define MMUIR_STEP TLB_STEP + +#define MMUDR_FIRST DTLB_FIXED +#define MMUDR_END DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP +#define MMUDR_STEP TLB_STEP + +/* Safety check : CONFIG_PAGE_OFFSET has to be a multiple of 512Mb */ +#if (CONFIG_PAGE_OFFSET & ((1UL<<29)-1)) +#error "CONFIG_PAGE_OFFSET must be a multiple of 512Mb" +#endif + +/* + * MMU defines: Fixed TLBs. + */ +/* Deal safely with the case where the base of RAM is not 512Mb aligned */ + +#define ALIGN_512M_MASK (0xffffffffe0000000) +#define ALIGNED_EFFECTIVE ((CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START) & ALIGN_512M_MASK) +#define ALIGNED_PHYSICAL (CONFIG_MEMORY_START & ALIGN_512M_MASK) + +#define MMUIR_TEXT_H (0x0000000000000003 | ALIGNED_EFFECTIVE) + /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ + +#define MMUIR_TEXT_L (0x000000000000009a | ALIGNED_PHYSICAL) + /* 512 Mb, Cacheable, Write-back, execute, Not User, Ph. Add. */ + +#define MMUDR_CACHED_H 0x0000000000000003 | ALIGNED_EFFECTIVE + /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ +#define MMUDR_CACHED_L 0x000000000000015a | ALIGNED_PHYSICAL + /* 512 Mb, Cacheable, Write-back, read/write, Not User, Ph. Add. */ + +#ifdef CONFIG_CACHE_OFF +#define ICCR0_INIT_VAL ICCR0_OFF /* ICACHE off */ +#else +#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */ +#endif +#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */ + +#if defined (CONFIG_CACHE_OFF) +#define OCCR0_INIT_VAL OCCR0_OFF /* D-cache: off */ +#elif defined (CONFIG_CACHE_WRITETHROUGH) +#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WT /* D-cache: on, */ + /* WT, invalidate */ +#elif defined (CONFIG_CACHE_WRITEBACK) +#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* D-cache: on, */ + /* WB, invalidate */ +#else +#error preprocessor flag CONFIG_CACHE_... not recognized! +#endif + +#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */ + + .section .empty_zero_page, "aw" + .global empty_zero_page + +empty_zero_page: + .long 1 /* MOUNT_ROOT_RDONLY */ + .long 0 /* RAMDISK_FLAGS */ + .long 0x0200 /* ORIG_ROOT_DEV */ + .long 1 /* LOADER_TYPE */ + .long 0x00800000 /* INITRD_START */ + .long 0x00800000 /* INITRD_SIZE */ + .long 0 + + .text + .balign 4096,0,4096 + + .section .data, "aw" + .balign PAGE_SIZE + + .section .data, "aw" + .balign PAGE_SIZE + + .global mmu_pdtp_cache +mmu_pdtp_cache: + .space PAGE_SIZE, 0 + + .global empty_bad_page +empty_bad_page: + .space PAGE_SIZE, 0 + + .global empty_bad_pte_table +empty_bad_pte_table: + .space PAGE_SIZE, 0 + + .global fpu_in_use +fpu_in_use: .quad 0 + + + .section .text.head, "ax" + .balign L1_CACHE_BYTES +/* + * Condition at the entry of __stext: + * . Reset state: + * . SR.FD = 1 (FPU disabled) + * . SR.BL = 1 (Exceptions disabled) + * . SR.MD = 1 (Privileged Mode) + * . SR.MMU = 0 (MMU Disabled) + * . SR.CD = 0 (CTC User Visible) + * . SR.IMASK = Undefined (Interrupt Mask) + * + * Operations supposed to be performed by __stext: + * . prevent speculative fetch onto device memory while MMU is off + * . reflect as much as possible SH5 ABI (r15, r26, r27, r18) + * . first, save CPU state and set it to something harmless + * . any CPU detection and/or endianness settings (?) + * . initialize EMI/LMI (but not TMU/RTC/INTC/SCIF): TBD + * . set initial TLB entries for cached and uncached regions + * (no fine granularity paging) + * . set initial cache state + * . enable MMU and caches + * . set CPU to a consistent state + * . registers (including stack pointer and current/KCR0) + * . NOT expecting to set Exception handling nor VBR/RESVEC/DCR + * at this stage. This is all to later Linux initialization steps. + * . initialize FPU + * . clear BSS + * . jump into start_kernel() + * . be prepared to hopeless start_kernel() returns. + * + */ + .global _stext +_stext: + /* + * Prevent speculative fetch on device memory due to + * uninitialized target registers. + */ + ptabs/u ZERO, tr0 + ptabs/u ZERO, tr1 + ptabs/u ZERO, tr2 + ptabs/u ZERO, tr3 + ptabs/u ZERO, tr4 + ptabs/u ZERO, tr5 + ptabs/u ZERO, tr6 + ptabs/u ZERO, tr7 + synci + + /* + * Read/Set CPU state. After this block: + * r29 = Initial SR + */ + getcon SR, r29 + movi SR_HARMLESS, r20 + putcon r20, SR + + /* + * Initialize EMI/LMI. To Be Done. + */ + + /* + * CPU detection and/or endianness settings (?). To Be Done. + * Pure PIC code here, please ! Just save state into r30. + * After this block: + * r30 = CPU type/Platform Endianness + */ + + /* + * Set initial TLB entries for cached and uncached regions. + * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! + */ + /* Clear ITLBs */ + pta clear_ITLB, tr1 + movi MMUIR_FIRST, r21 + movi MMUIR_END, r22 +clear_ITLB: + putcfg r21, 0, ZERO /* Clear MMUIR[n].PTEH.V */ + addi r21, MMUIR_STEP, r21 + bne r21, r22, tr1 + + /* Clear DTLBs */ + pta clear_DTLB, tr1 + movi MMUDR_FIRST, r21 + movi MMUDR_END, r22 +clear_DTLB: + putcfg r21, 0, ZERO /* Clear MMUDR[n].PTEH.V */ + addi r21, MMUDR_STEP, r21 + bne r21, r22, tr1 + + /* Map one big (512Mb) page for ITLB */ + movi MMUIR_FIRST, r21 + movi MMUIR_TEXT_L, r22 /* PTEL first */ + add.l r22, r63, r22 /* Sign extend */ + putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */ + movi MMUIR_TEXT_H, r22 /* PTEH last */ + add.l r22, r63, r22 /* Sign extend */ + putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */ + + /* Map one big CACHED (512Mb) page for DTLB */ + movi MMUDR_FIRST, r21 + movi MMUDR_CACHED_L, r22 /* PTEL first */ + add.l r22, r63, r22 /* Sign extend */ + putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */ + movi MMUDR_CACHED_H, r22 /* PTEH last */ + add.l r22, r63, r22 /* Sign extend */ + putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ + +#ifdef CONFIG_EARLY_PRINTK + /* + * Setup a DTLB translation for SCIF phys. + */ + addi r21, MMUDR_STEP, r21 + movi 0x0a03, r22 /* SCIF phys */ + shori 0x0148, r22 + putcfg r21, 1, r22 /* PTEL first */ + movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ + shori 0x0003, r22 + putcfg r21, 0, r22 /* PTEH last */ +#endif + + /* + * Set cache behaviours. + */ + /* ICache */ + movi ICCR_BASE, r21 + movi ICCR0_INIT_VAL, r22 + movi ICCR1_INIT_VAL, r23 + putcfg r21, ICCR_REG0, r22 + putcfg r21, ICCR_REG1, r23 + + /* OCache */ + movi OCCR_BASE, r21 + movi OCCR0_INIT_VAL, r22 + movi OCCR1_INIT_VAL, r23 + putcfg r21, OCCR_REG0, r22 + putcfg r21, OCCR_REG1, r23 + + + /* + * Enable Caches and MMU. Do the first non-PIC jump. + * Now head.S global variables, constants and externs + * can be used. + */ + getcon SR, r21 + movi SR_ENABLE_MMU, r22 + or r21, r22, r21 + putcon r21, SSR + movi hyperspace, r22 + ori r22, 1, r22 /* Make it SHmedia, not required but..*/ + putcon r22, SPC + synco + rte /* And now go into the hyperspace ... */ +hyperspace: /* ... that's the next instruction ! */ + + /* + * Set CPU to a consistent state. + * r31 = FPU support flag + * tr0/tr7 in use. Others give a chance to loop somewhere safe + */ + movi start_kernel, r32 + ori r32, 1, r32 + + ptabs r32, tr0 /* r32 = _start_kernel address */ + pta/u hopeless, tr1 + pta/u hopeless, tr2 + pta/u hopeless, tr3 + pta/u hopeless, tr4 + pta/u hopeless, tr5 + pta/u hopeless, tr6 + pta/u hopeless, tr7 + gettr tr1, r28 /* r28 = hopeless address */ + + /* Set initial stack pointer */ + movi init_thread_union, SP + putcon SP, KCR0 /* Set current to init_task */ + movi THREAD_SIZE, r22 /* Point to the end */ + add SP, r22, SP + + /* + * Initialize FPU. + * Keep FPU flag in r31. After this block: + * r31 = FPU flag + */ + movi fpu_in_use, r31 /* Temporary */ + +#ifdef CONFIG_SH_FPU + getcon SR, r21 + movi SR_ENABLE_FPU, r22 + and r21, r22, r22 + putcon r22, SR /* Try to enable */ + getcon SR, r22 + xor r21, r22, r21 + shlri r21, 15, r21 /* Supposedly 0/1 */ + st.q r31, 0 , r21 /* Set fpu_in_use */ +#else + movi 0, r21 + st.q r31, 0 , r21 /* Set fpu_in_use */ +#endif + or r21, ZERO, r31 /* Set FPU flag at last */ + +#ifndef CONFIG_SH_NO_BSS_INIT +/* Don't clear BSS if running on slow platforms such as an RTL simulation, + remote memory via SHdebug link, etc. For these the memory can be guaranteed + to be all zero on boot anyway. */ + /* + * Clear bss + */ + pta clear_quad, tr1 + movi __bss_start, r22 + movi _end, r23 +clear_quad: + st.q r22, 0, ZERO + addi r22, 8, r22 + bne r22, r23, tr1 /* Both quad aligned, see vmlinux.lds.S */ +#endif + pta/u hopeless, tr1 + + /* Say bye to head.S but be prepared to wrongly get back ... */ + blink tr0, LINK + + /* If we ever get back here through LINK/tr1-tr7 */ + pta/u hopeless, tr7 + +hopeless: + /* + * Something's badly wrong here. Loop endlessly, + * there's nothing more we can do about it. + * + * Note on hopeless: it can be jumped into invariably + * before or after jumping into hyperspace. The only + * requirement is to be PIC called (PTA) before and + * any way (PTA/PTABS) after. According to Virtual + * to Physical mapping a simulator/emulator can easily + * tell where we came here from just looking at hopeless + * (PC) address. + * + * For debugging purposes: + * (r28) hopeless/loop address + * (r29) Original SR + * (r30) CPU type/Platform endianness + * (r31) FPU Support + * (r32) _start_kernel address + */ + blink tr7, ZERO diff -puN arch/sh/kernel/init_task.c~git-sh arch/sh/kernel/init_task.c --- a/arch/sh/kernel/init_task.c~git-sh +++ a/arch/sh/kernel/init_task.c @@ -11,8 +11,8 @@ static struct fs_struct init_fs = INIT_F 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 pt_regs fake_swapper_regs; struct mm_struct init_mm = INIT_MM(init_mm); - EXPORT_SYMBOL(init_mm); /* @@ -22,7 +22,7 @@ EXPORT_SYMBOL(init_mm); * way process stacks are handled. This is done by having a special * "init_task" linker map entry.. */ -union thread_union init_thread_union +union thread_union init_thread_union __attribute__((__section__(".data.init_task"))) = { INIT_THREAD_INFO(init_task) }; diff -puN arch/sh/kernel/io.c~git-sh arch/sh/kernel/io.c --- a/arch/sh/kernel/io.c~git-sh +++ a/arch/sh/kernel/io.c @@ -61,73 +61,6 @@ void memset_io(volatile void __iomem *ds } EXPORT_SYMBOL(memset_io); -void __raw_readsl(unsigned long addr, void *datap, int len) -{ - u32 *data; - - for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--) - *data++ = ctrl_inl(addr); - - if (likely(len >= (0x20 >> 2))) { - int tmp2, tmp3, tmp4, tmp5, tmp6; - - __asm__ __volatile__( - "1: \n\t" - "mov.l @%7, r0 \n\t" - "mov.l @%7, %2 \n\t" -#ifdef CONFIG_CPU_SH4 - "movca.l r0, @%0 \n\t" -#else - "mov.l r0, @%0 \n\t" -#endif - "mov.l @%7, %3 \n\t" - "mov.l @%7, %4 \n\t" - "mov.l @%7, %5 \n\t" - "mov.l @%7, %6 \n\t" - "mov.l @%7, r7 \n\t" - "mov.l @%7, r0 \n\t" - "mov.l %2, @(0x04,%0) \n\t" - "mov #0x20>>2, %2 \n\t" - "mov.l %3, @(0x08,%0) \n\t" - "sub %2, %1 \n\t" - "mov.l %4, @(0x0c,%0) \n\t" - "cmp/hi %1, %2 ! T if 32 > len \n\t" - "mov.l %5, @(0x10,%0) \n\t" - "mov.l %6, @(0x14,%0) \n\t" - "mov.l r7, @(0x18,%0) \n\t" - "mov.l r0, @(0x1c,%0) \n\t" - "bf.s 1b \n\t" - " add #0x20, %0 \n\t" - : "=&r" (data), "=&r" (len), - "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4), - "=&r" (tmp5), "=&r" (tmp6) - : "r"(addr), "0" (data), "1" (len) - : "r0", "r7", "t", "memory"); - } - - for (; len != 0; len--) - *data++ = ctrl_inl(addr); -} -EXPORT_SYMBOL(__raw_readsl); - -void __raw_writesl(unsigned long addr, const void *data, int len) -{ - if (likely(len != 0)) { - int tmp1; - - __asm__ __volatile__ ( - "1: \n\t" - "mov.l @%0+, %1 \n\t" - "dt %3 \n\t" - "bf.s 1b \n\t" - " mov.l %1, @%4 \n\t" - : "=&r" (data), "=&r" (tmp1) - : "0" (data), "r" (len), "r"(addr) - : "t", "memory"); - } -} -EXPORT_SYMBOL(__raw_writesl); - void __iomem *ioport_map(unsigned long port, unsigned int nr) { return sh_mv.mv_ioport_map(port, nr); diff -puN arch/sh/kernel/module.c~git-sh arch/sh/kernel/module.c --- a/arch/sh/kernel/module.c~git-sh +++ a/arch/sh/kernel/module.c @@ -1,5 +1,15 @@ /* Kernel module help for SH. + SHcompact version by Kaz Kojima and Paul Mundt. + + SHmedia bits: + + Copyright 2004 SuperH (UK) Ltd + Author: Richard Curnow + + Based on the sh version, and on code from the sh64-specific parts of + modutils, originally written by Richard Curnow and Ben Gaster. + 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 @@ -21,12 +31,6 @@ #include #include -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - void *module_alloc(unsigned long size) { if (size == 0) @@ -52,6 +56,7 @@ int module_frob_arch_sections(Elf_Ehdr * return 0; } +#ifdef CONFIG_SUPERH32 #define COPY_UNALIGNED_WORD(sw, tw, align) \ { \ void *__s = &(sw), *__t = &(tw); \ @@ -74,6 +79,10 @@ int module_frob_arch_sections(Elf_Ehdr * break; \ } \ } +#else +/* One thing SHmedia doesn't screw up! */ +#define COPY_UNALIGNED_WORD(sw, tw, align) { (tw) = (sw); } +#endif int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab, @@ -89,8 +98,8 @@ int apply_relocate_add(Elf32_Shdr *sechd uint32_t value; int align; - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); + pr_debug("Applying relocate section %u to %u\n", relsec, + sechdrs[relsec].sh_info); for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { /* This is where to make the change */ location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr @@ -102,17 +111,44 @@ int apply_relocate_add(Elf32_Shdr *sechd relocation = sym->st_value + rel[i].r_addend; align = (int)location & 3; +#ifdef CONFIG_SUPERH64 + /* For text addresses, bit2 of the st_other field indicates + * whether the symbol is SHmedia (1) or SHcompact (0). If + * SHmedia, the LSB of the symbol needs to be asserted + * for the CPU to be in SHmedia mode when it starts executing + * the branch target. */ + relocation |= (sym->st_other & 4); +#endif + switch (ELF32_R_TYPE(rel[i].r_info)) { case R_SH_DIR32: - COPY_UNALIGNED_WORD (*location, value, align); + COPY_UNALIGNED_WORD (*location, value, align); value += relocation; - COPY_UNALIGNED_WORD (value, *location, align); + COPY_UNALIGNED_WORD (value, *location, align); break; case R_SH_REL32: - relocation = (relocation - (Elf32_Addr) location); - COPY_UNALIGNED_WORD (*location, value, align); + relocation = (relocation - (Elf32_Addr) location); + COPY_UNALIGNED_WORD (*location, value, align); value += relocation; - COPY_UNALIGNED_WORD (value, *location, align); + COPY_UNALIGNED_WORD (value, *location, align); + break; + case R_SH_IMM_LOW16: + *location = (*location & ~0x3fffc00) | + ((relocation & 0xffff) << 10); + break; + case R_SH_IMM_MEDLOW16: + *location = (*location & ~0x3fffc00) | + (((relocation >> 16) & 0xffff) << 10); + break; + case R_SH_IMM_LOW16_PCREL: + relocation -= (Elf32_Addr) location; + *location = (*location & ~0x3fffc00) | + ((relocation & 0xffff) << 10); + break; + case R_SH_IMM_MEDLOW16_PCREL: + relocation -= (Elf32_Addr) location; + *location = (*location & ~0x3fffc00) | + (((relocation >> 16) & 0xffff) << 10); break; default: printk(KERN_ERR "module %s: Unknown relocation: %u\n", diff -puN arch/sh/kernel/process.c~git-sh /dev/null --- a/arch/sh/kernel/process.c +++ /dev/null @@ -1,558 +0,0 @@ -/* - * arch/sh/kernel/process.c - * - * This file handles the architecture-dependent parts of process handling.. - * - * Copyright (C) 1995 Linus Torvalds - * - * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC - * Copyright (C) 2002 - 2007 Paul Mundt - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int hlt_counter; -int ubc_usercnt = 0; - -void (*pm_idle)(void); -void (*pm_power_off)(void); -EXPORT_SYMBOL(pm_power_off); - -void disable_hlt(void) -{ - hlt_counter++; -} -EXPORT_SYMBOL(disable_hlt); - -void enable_hlt(void) -{ - hlt_counter--; -} -EXPORT_SYMBOL(enable_hlt); - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} -__setup("nohlt", nohlt_setup); - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} -__setup("hlt", hlt_setup); - -void default_idle(void) -{ - if (!hlt_counter) { - clear_thread_flag(TIF_POLLING_NRFLAG); - smp_mb__after_clear_bit(); - set_bl_bit(); - while (!need_resched()) - cpu_sleep(); - clear_bl_bit(); - set_thread_flag(TIF_POLLING_NRFLAG); - } else - while (!need_resched()) - cpu_relax(); -} - -void cpu_idle(void) -{ - set_thread_flag(TIF_POLLING_NRFLAG); - - /* endless idle loop with no priority at all */ - while (1) { - void (*idle)(void) = pm_idle; - - if (!idle) - idle = default_idle; - - tick_nohz_stop_sched_tick(); - while (!need_resched()) - idle(); - tick_nohz_restart_sched_tick(); - - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - check_pgt_cache(); - } -} - -void machine_restart(char * __unused) -{ - /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ - asm volatile("ldc %0, sr\n\t" - "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); -} - -void machine_halt(void) -{ - local_irq_disable(); - - while (1) - cpu_sleep(); -} - -void machine_power_off(void) -{ - if (pm_power_off) - pm_power_off(); -} - -void show_regs(struct pt_regs * regs) -{ - printk("\n"); - printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm); - print_symbol("PC is at %s\n", instruction_pointer(regs)); - printk("PC : %08lx SP : %08lx SR : %08lx ", - regs->pc, regs->regs[15], regs->sr); -#ifdef CONFIG_MMU - printk("TEA : %08x ", ctrl_inl(MMU_TEA)); -#else - printk(" "); -#endif - printk("%s\n", print_tainted()); - - printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", - regs->regs[0],regs->regs[1], - regs->regs[2],regs->regs[3]); - printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", - regs->regs[4],regs->regs[5], - regs->regs[6],regs->regs[7]); - printk("R8 : %08lx R9 : %08lx R10 : %08lx R11 : %08lx\n", - regs->regs[8],regs->regs[9], - regs->regs[10],regs->regs[11]); - printk("R12 : %08lx R13 : %08lx R14 : %08lx\n", - regs->regs[12],regs->regs[13], - regs->regs[14]); - printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", - regs->mach, regs->macl, regs->gbr, regs->pr); - - show_trace(NULL, (unsigned long *)regs->regs[15], regs); -} - -/* - * Create a kernel thread - */ - -/* - * This is the mechanism for creating a new kernel thread. - * - */ -extern void kernel_thread_helper(void); -__asm__(".align 5\n" - "kernel_thread_helper:\n\t" - "jsr @r5\n\t" - " nop\n\t" - "mov.l 1f, r1\n\t" - "jsr @r1\n\t" - " mov r0, r4\n\t" - ".align 2\n\t" - "1:.long do_exit"); - -/* Don't use this in BL=1(cli). Or else, CPU resets! */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - regs.regs[4] = (unsigned long)arg; - regs.regs[5] = (unsigned long)fn; - - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = (1 << 30); - - /* Ok, create the new process.. */ - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); -} - -/* - * Free current thread data structures etc.. - */ -void exit_thread(void) -{ - if (current->thread.ubc_pc) { - current->thread.ubc_pc = 0; - ubc_usercnt -= 1; - } -} - -void flush_thread(void) -{ -#if defined(CONFIG_SH_FPU) - struct task_struct *tsk = current; - /* Forget lazy FPU state */ - clear_fpu(tsk, task_pt_regs(tsk)); - clear_used_math(); -#endif -} - -void release_thread(struct task_struct *dead_task) -{ - /* do nothing */ -} - -/* Fill in the fpu structure for a core dump.. */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -{ - int fpvalid = 0; - -#if defined(CONFIG_SH_FPU) - struct task_struct *tsk = current; - - fpvalid = !!tsk_used_math(tsk); - if (fpvalid) { - unlazy_fpu(tsk, regs); - memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); - } -#endif - - return fpvalid; -} - -/* - * Capture the user space registers if the task is not running (in user space) - */ -int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) -{ - struct pt_regs ptregs; - - ptregs = *task_pt_regs(tsk); - elf_core_copy_regs(regs, &ptregs); - - return 1; -} - -int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpu) -{ - int fpvalid = 0; - -#if defined(CONFIG_SH_FPU) - fpvalid = !!tsk_used_math(tsk); - if (fpvalid) { - unlazy_fpu(tsk, task_pt_regs(tsk)); - memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); - } -#endif - - return fpvalid; -} - -asmlinkage void ret_from_fork(void); - -int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct thread_info *ti = task_thread_info(p); - struct pt_regs *childregs; -#if defined(CONFIG_SH_FPU) - struct task_struct *tsk = current; - - unlazy_fpu(tsk, regs); - p->thread.fpu = tsk->thread.fpu; - copy_to_stopped_child_used_math(p); -#endif - - childregs = task_pt_regs(p); - *childregs = *regs; - - if (user_mode(regs)) { - childregs->regs[15] = usp; - ti->addr_limit = USER_DS; - } else { - childregs->regs[15] = (unsigned long)childregs; - ti->addr_limit = KERNEL_DS; - } - - if (clone_flags & CLONE_SETTLS) - childregs->gbr = childregs->regs[0]; - - childregs->regs[0] = 0; /* Set return value for child */ - - p->thread.sp = (unsigned long) childregs; - p->thread.pc = (unsigned long) ret_from_fork; - - p->thread.ubc_pc = 0; - - return 0; -} - -/* Tracing by user break controller. */ -static void ubc_set_tracing(int asid, unsigned long pc) -{ -#if defined(CONFIG_CPU_SH4A) - unsigned long val; - - val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE); - val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid)); - - ctrl_outl(val, UBC_CBR0); - ctrl_outl(pc, UBC_CAR0); - ctrl_outl(0x0, UBC_CAMR0); - ctrl_outl(0x0, UBC_CBCR); - - val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE); - ctrl_outl(val, UBC_CRR0); - - /* Read UBC register that we wrote last, for checking update */ - val = ctrl_inl(UBC_CRR0); - -#else /* CONFIG_CPU_SH4A */ - ctrl_outl(pc, UBC_BARA); - -#ifdef CONFIG_MMU - ctrl_outb(asid, UBC_BASRA); -#endif - - ctrl_outl(0, UBC_BAMRA); - - if (current_cpu_data.type == CPU_SH7729 || - current_cpu_data.type == CPU_SH7710 || - current_cpu_data.type == CPU_SH7712) { - ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); - ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR); - } else { - ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); - ctrl_outw(BRCR_PCBA, UBC_BRCR); - } -#endif /* CONFIG_CPU_SH4A */ -} - -/* - * switch_to(x,y) should switch tasks from x to y. - * - */ -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *next) -{ -#if defined(CONFIG_SH_FPU) - unlazy_fpu(prev, task_pt_regs(prev)); -#endif - -#if defined(CONFIG_GUSA) && defined(CONFIG_PREEMPT) - { - struct pt_regs *regs; - - preempt_disable(); - regs = task_pt_regs(prev); - if (user_mode(regs) && regs->regs[15] >= 0xc0000000) { - int offset = (int)regs->regs[15]; - - /* Reset stack pointer: clear critical region mark */ - regs->regs[15] = regs->regs[1]; - if (regs->pc < regs->regs[0]) - /* Go to rewind point */ - regs->pc = regs->regs[0] + offset; - } - preempt_enable_no_resched(); - } -#endif - -#ifdef CONFIG_MMU - /* - * Restore the kernel mode register - * k7 (r7_bank1) - */ - asm volatile("ldc %0, r7_bank" - : /* no output */ - : "r" (task_thread_info(next))); -#endif - - /* If no tasks are using the UBC, we're done */ - if (ubc_usercnt == 0) - /* If no tasks are using the UBC, we're done */; - else if (next->thread.ubc_pc && next->mm) { - int asid = 0; -#ifdef CONFIG_MMU - asid |= cpu_asid(smp_processor_id(), next->mm); -#endif - ubc_set_tracing(asid, next->thread.ubc_pc); - } else { -#if defined(CONFIG_CPU_SH4A) - ctrl_outl(UBC_CBR_INIT, UBC_CBR0); - ctrl_outl(UBC_CRR_INIT, UBC_CRR0); -#else - ctrl_outw(0, UBC_BBRA); - ctrl_outw(0, UBC_BBRB); -#endif - } - - return prev; -} - -asmlinkage int sys_fork(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ -#ifdef CONFIG_MMU - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); -#else - /* fork almost works, enough to trick you into looking elsewhere :-( */ - return -EINVAL; -#endif -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - unsigned long parent_tidptr, - unsigned long child_tidptr, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - if (!newsp) - newsp = regs->regs[15]; - return do_fork(clone_flags, newsp, regs, 0, - (int __user *)parent_tidptr, - (int __user *)child_tidptr); -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, - 0, NULL, NULL); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, - char __user * __user *uenvp, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - int error; - char *filename; - - filename = getname(ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename, uargv, uenvp, regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - return error; -} - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long pc; - - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - /* - * The same comment as on the Alpha applies here, too ... - */ - pc = thread_saved_pc(p); - -#ifdef CONFIG_FRAME_POINTER - if (in_sched_functions(pc)) { - unsigned long schedule_frame = (unsigned long)p->thread.sp; - return ((unsigned long *)schedule_frame)[21]; - } -#endif - - return pc; -} - -asmlinkage void break_point_trap(void) -{ - /* Clear tracing. */ -#if defined(CONFIG_CPU_SH4A) - ctrl_outl(UBC_CBR_INIT, UBC_CBR0); - ctrl_outl(UBC_CRR_INIT, UBC_CRR0); -#else - ctrl_outw(0, UBC_BBRA); - ctrl_outw(0, UBC_BBRB); -#endif - current->thread.ubc_pc = 0; - ubc_usercnt -= 1; - - force_sig(SIGTRAP, current); -} - -/* - * Generic trap handler. - */ -asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - - /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); - - if (notify_die(DIE_TRAP, "debug trap", regs, 0, regs->tra & 0xff, - SIGTRAP) == NOTIFY_STOP) - return; - - force_sig(SIGTRAP, current); -} - -/* - * Special handler for BUG() traps. - */ -asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - - /* Rewind */ - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); - - if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, - SIGTRAP) == NOTIFY_STOP) - return; - -#ifdef CONFIG_BUG - if (__kernel_text_address(instruction_pointer(regs))) { - u16 insn = *(u16 *)instruction_pointer(regs); - if (insn == TRAPA_BUG_OPCODE) - handle_BUG(regs); - } -#endif - - force_sig(SIGTRAP, current); -} diff -puN /dev/null arch/sh/kernel/process_32.c --- /dev/null +++ a/arch/sh/kernel/process_32.c @@ -0,0 +1,465 @@ +/* + * arch/sh/kernel/process.c + * + * This file handles the architecture-dependent parts of process handling.. + * + * Copyright (C) 1995 Linus Torvalds + * + * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima + * Copyright (C) 2006 Lineo Solutions Inc. support SH4A UBC + * Copyright (C) 2002 - 2007 Paul Mundt + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int hlt_counter; +int ubc_usercnt = 0; + +void (*pm_idle)(void); +void (*pm_power_off)(void); +EXPORT_SYMBOL(pm_power_off); + +void disable_hlt(void) +{ + hlt_counter++; +} +EXPORT_SYMBOL(disable_hlt); + +void enable_hlt(void) +{ + hlt_counter--; +} +EXPORT_SYMBOL(enable_hlt); + +static int __init nohlt_setup(char *__unused) +{ + hlt_counter = 1; + return 1; +} +__setup("nohlt", nohlt_setup); + +static int __init hlt_setup(char *__unused) +{ + hlt_counter = 0; + return 1; +} +__setup("hlt", hlt_setup); + +void default_idle(void) +{ + if (!hlt_counter) { + clear_thread_flag(TIF_POLLING_NRFLAG); + smp_mb__after_clear_bit(); + set_bl_bit(); + while (!need_resched()) + cpu_sleep(); + clear_bl_bit(); + set_thread_flag(TIF_POLLING_NRFLAG); + } else + while (!need_resched()) + cpu_relax(); +} + +void cpu_idle(void) +{ + set_thread_flag(TIF_POLLING_NRFLAG); + + /* endless idle loop with no priority at all */ + while (1) { + void (*idle)(void) = pm_idle; + + if (!idle) + idle = default_idle; + + tick_nohz_stop_sched_tick(); + while (!need_resched()) + idle(); + tick_nohz_restart_sched_tick(); + + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + check_pgt_cache(); + } +} + +void machine_restart(char * __unused) +{ + /* SR.BL=1 and invoke address error to let CPU reset (manual reset) */ + asm volatile("ldc %0, sr\n\t" + "mov.l @%1, %0" : : "r" (0x10000000), "r" (0x80000001)); +} + +void machine_halt(void) +{ + local_irq_disable(); + + while (1) + cpu_sleep(); +} + +void machine_power_off(void) +{ + if (pm_power_off) + pm_power_off(); +} + +void show_regs(struct pt_regs * regs) +{ + printk("\n"); + printk("Pid : %d, Comm: %20s\n", task_pid_nr(current), current->comm); + print_symbol("PC is at %s\n", instruction_pointer(regs)); + printk("PC : %08lx SP : %08lx SR : %08lx ", + regs->pc, regs->regs[15], regs->sr); +#ifdef CONFIG_MMU + printk("TEA : %08x ", ctrl_inl(MMU_TEA)); +#else + printk(" "); +#endif + printk("%s\n", print_tainted()); + + printk("R0 : %08lx R1 : %08lx R2 : %08lx R3 : %08lx\n", + regs->regs[0],regs->regs[1], + regs->regs[2],regs->regs[3]); + printk("R4 : %08lx R5 : %08lx R6 : %08lx R7 : %08lx\n", + regs->regs[4],regs->regs[5], + regs->regs[6],regs->regs[7]); + printk("R8 : %08lx R9 : %08lx R10 : %08lx R11 : %08lx\n", + regs->regs[8],regs->regs[9], + regs->regs[10],regs->regs[11]); + printk("R12 : %08lx R13 : %08lx R14 : %08lx\n", + regs->regs[12],regs->regs[13], + regs->regs[14]); + printk("MACH: %08lx MACL: %08lx GBR : %08lx PR : %08lx\n", + regs->mach, regs->macl, regs->gbr, regs->pr); + + show_trace(NULL, (unsigned long *)regs->regs[15], regs); +} + +/* + * Create a kernel thread + */ + +/* + * This is the mechanism for creating a new kernel thread. + * + */ +extern void kernel_thread_helper(void); +__asm__(".align 5\n" + "kernel_thread_helper:\n\t" + "jsr @r5\n\t" + " nop\n\t" + "mov.l 1f, r1\n\t" + "jsr @r1\n\t" + " mov r0, r4\n\t" + ".align 2\n\t" + "1:.long do_exit"); + +/* Don't use this in BL=1(cli). Or else, CPU resets! */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.regs[4] = (unsigned long)arg; + regs.regs[5] = (unsigned long)fn; + + regs.pc = (unsigned long)kernel_thread_helper; + regs.sr = (1 << 30); + + /* Ok, create the new process.. */ + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + ®s, 0, NULL, NULL); +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ + if (current->thread.ubc_pc) { + current->thread.ubc_pc = 0; + ubc_usercnt -= 1; + } +} + +void flush_thread(void) +{ +#if defined(CONFIG_SH_FPU) + struct task_struct *tsk = current; + /* Forget lazy FPU state */ + clear_fpu(tsk, task_pt_regs(tsk)); + clear_used_math(); +#endif +} + +void release_thread(struct task_struct *dead_task) +{ + /* do nothing */ +} + +/* Fill in the fpu structure for a core dump.. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) +{ + int fpvalid = 0; + +#if defined(CONFIG_SH_FPU) + struct task_struct *tsk = current; + + fpvalid = !!tsk_used_math(tsk); + if (fpvalid) { + unlazy_fpu(tsk, regs); + memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); + } +#endif + + return fpvalid; +} + +asmlinkage void ret_from_fork(void); + +int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) +{ + struct thread_info *ti = task_thread_info(p); + struct pt_regs *childregs; +#if defined(CONFIG_SH_FPU) + struct task_struct *tsk = current; + + unlazy_fpu(tsk, regs); + p->thread.fpu = tsk->thread.fpu; + copy_to_stopped_child_used_math(p); +#endif + + childregs = task_pt_regs(p); + *childregs = *regs; + + if (user_mode(regs)) { + childregs->regs[15] = usp; + ti->addr_limit = USER_DS; + } else { + childregs->regs[15] = (unsigned long)childregs; + ti->addr_limit = KERNEL_DS; + } + + if (clone_flags & CLONE_SETTLS) + childregs->gbr = childregs->regs[0]; + + childregs->regs[0] = 0; /* Set return value for child */ + + p->thread.sp = (unsigned long) childregs; + p->thread.pc = (unsigned long) ret_from_fork; + + p->thread.ubc_pc = 0; + + return 0; +} + +/* Tracing by user break controller. */ +static void ubc_set_tracing(int asid, unsigned long pc) +{ +#if defined(CONFIG_CPU_SH4A) + unsigned long val; + + val = (UBC_CBR_ID_INST | UBC_CBR_RW_READ | UBC_CBR_CE); + val |= (UBC_CBR_AIE | UBC_CBR_AIV_SET(asid)); + + ctrl_outl(val, UBC_CBR0); + ctrl_outl(pc, UBC_CAR0); + ctrl_outl(0x0, UBC_CAMR0); + ctrl_outl(0x0, UBC_CBCR); + + val = (UBC_CRR_RES | UBC_CRR_PCB | UBC_CRR_BIE); + ctrl_outl(val, UBC_CRR0); + + /* Read UBC register that we wrote last, for checking update */ + val = ctrl_inl(UBC_CRR0); + +#else /* CONFIG_CPU_SH4A */ + ctrl_outl(pc, UBC_BARA); + +#ifdef CONFIG_MMU + ctrl_outb(asid, UBC_BASRA); +#endif + + ctrl_outl(0, UBC_BAMRA); + + if (current_cpu_data.type == CPU_SH7729 || + current_cpu_data.type == CPU_SH7710 || + current_cpu_data.type == CPU_SH7712) { + ctrl_outw(BBR_INST | BBR_READ | BBR_CPU, UBC_BBRA); + ctrl_outl(BRCR_PCBA | BRCR_PCTE, UBC_BRCR); + } else { + ctrl_outw(BBR_INST | BBR_READ, UBC_BBRA); + ctrl_outw(BRCR_PCBA, UBC_BRCR); + } +#endif /* CONFIG_CPU_SH4A */ +} + +/* + * switch_to(x,y) should switch tasks from x to y. + * + */ +struct task_struct *__switch_to(struct task_struct *prev, + struct task_struct *next) +{ +#if defined(CONFIG_SH_FPU) + unlazy_fpu(prev, task_pt_regs(prev)); +#endif + +#ifdef CONFIG_MMU + /* + * Restore the kernel mode register + * k7 (r7_bank1) + */ + asm volatile("ldc %0, r7_bank" + : /* no output */ + : "r" (task_thread_info(next))); +#endif + + /* If no tasks are using the UBC, we're done */ + if (ubc_usercnt == 0) + /* If no tasks are using the UBC, we're done */; + else if (next->thread.ubc_pc && next->mm) { + int asid = 0; +#ifdef CONFIG_MMU + asid |= cpu_asid(smp_processor_id(), next->mm); +#endif + ubc_set_tracing(asid, next->thread.ubc_pc); + } else { +#if defined(CONFIG_CPU_SH4A) + ctrl_outl(UBC_CBR_INIT, UBC_CBR0); + ctrl_outl(UBC_CRR_INIT, UBC_CRR0); +#else + ctrl_outw(0, UBC_BBRA); + ctrl_outw(0, UBC_BBRB); +#endif + } + + return prev; +} + +asmlinkage int sys_fork(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ +#ifdef CONFIG_MMU + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + return do_fork(SIGCHLD, regs->regs[15], regs, 0, NULL, NULL); +#else + /* fork almost works, enough to trick you into looking elsewhere :-( */ + return -EINVAL; +#endif +} + +asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, + unsigned long parent_tidptr, + unsigned long child_tidptr, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + if (!newsp) + newsp = regs->regs[15]; + return do_fork(clone_flags, newsp, regs, 0, + (int __user *)parent_tidptr, + (int __user *)child_tidptr); +} + +/* + * This is trivial, and on the face of it looks like it + * could equally well be done in user mode. + * + * Not so, for quite unobvious reasons - register pressure. + * In user mode vfork() cannot have a stack frame, and if + * done by calling the "clone()" system call directly, you + * do not have enough call-clobbered registers to hold all + * the information you need. + */ +asmlinkage int sys_vfork(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->regs[15], regs, + 0, NULL, NULL); +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(char __user *ufilename, char __user * __user *uargv, + char __user * __user *uenvp, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + int error; + char *filename; + + filename = getname(ufilename); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + + error = do_execve(filename, uargv, uenvp, regs); + if (error == 0) { + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } + putname(filename); +out: + return error; +} + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long pc; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + /* + * The same comment as on the Alpha applies here, too ... + */ + pc = thread_saved_pc(p); + +#ifdef CONFIG_FRAME_POINTER + if (in_sched_functions(pc)) { + unsigned long schedule_frame = (unsigned long)p->thread.sp; + return ((unsigned long *)schedule_frame)[21]; + } +#endif + + return pc; +} + +asmlinkage void break_point_trap(void) +{ + /* Clear tracing. */ +#if defined(CONFIG_CPU_SH4A) + ctrl_outl(UBC_CBR_INIT, UBC_CBR0); + ctrl_outl(UBC_CRR_INIT, UBC_CRR0); +#else + ctrl_outw(0, UBC_BBRA); + ctrl_outw(0, UBC_BBRB); +#endif + current->thread.ubc_pc = 0; + ubc_usercnt -= 1; + + force_sig(SIGTRAP, current); +} diff -puN /dev/null arch/sh/kernel/process_64.c --- /dev/null +++ a/arch/sh/kernel/process_64.c @@ -0,0 +1,701 @@ +/* + * arch/sh/kernel/process_64.c + * + * This file handles the architecture-dependent parts of process handling.. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * Copyright (C) 2003, 2004 Richard Curnow + * + * Started from SH3/4 version: + * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima + * + * In turn started from i386 version: + * Copyright (C) 1995 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct task_struct *last_task_used_math = NULL; + +static int hlt_counter = 1; + +#define HARD_IDLE_TIMEOUT (HZ / 3) + +void disable_hlt(void) +{ + hlt_counter++; +} + +void enable_hlt(void) +{ + hlt_counter--; +} + +static int __init nohlt_setup(char *__unused) +{ + hlt_counter = 1; + return 1; +} + +static int __init hlt_setup(char *__unused) +{ + hlt_counter = 0; + return 1; +} + +__setup("nohlt", nohlt_setup); +__setup("hlt", hlt_setup); + +static inline void hlt(void) +{ + __asm__ __volatile__ ("sleep" : : : "memory"); +} + +/* + * The idle loop on a uniprocessor SH.. + */ +void cpu_idle(void) +{ + /* endless idle loop with no priority at all */ + while (1) { + if (hlt_counter) { + while (!need_resched()) + cpu_relax(); + } else { + local_irq_disable(); + while (!need_resched()) { + local_irq_enable(); + hlt(); + local_irq_disable(); + } + local_irq_enable(); + } + preempt_enable_no_resched(); + schedule(); + preempt_disable(); + } + +} + +void machine_restart(char * __unused) +{ + extern void phys_stext(void); + + phys_stext(); +} + +void machine_halt(void) +{ + for (;;); +} + +void machine_power_off(void) +{ +#if 0 + /* Disable watchdog timer */ + ctrl_outl(0xa5000000, WTCSR); + /* Configure deep standby on sleep */ + ctrl_outl(0x03, STBCR); +#endif + + __asm__ __volatile__ ( + "sleep\n\t" + "synci\n\t" + "nop;nop;nop;nop\n\t" + ); + + panic("Unexpected wakeup!\n"); +} + +void (*pm_power_off)(void) = machine_power_off; +EXPORT_SYMBOL(pm_power_off); + +void show_regs(struct pt_regs * regs) +{ + unsigned long long ah, al, bh, bl, ch, cl; + + printk("\n"); + + ah = (regs->pc) >> 32; + al = (regs->pc) & 0xffffffff; + bh = (regs->regs[18]) >> 32; + bl = (regs->regs[18]) & 0xffffffff; + ch = (regs->regs[15]) >> 32; + cl = (regs->regs[15]) & 0xffffffff; + printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->sr) >> 32; + al = (regs->sr) & 0xffffffff; + asm volatile ("getcon " __TEA ", %0" : "=r" (bh)); + asm volatile ("getcon " __TEA ", %0" : "=r" (bl)); + bh = (bh) >> 32; + bl = (bl) & 0xffffffff; + asm volatile ("getcon " __KCR0 ", %0" : "=r" (ch)); + asm volatile ("getcon " __KCR0 ", %0" : "=r" (cl)); + ch = (ch) >> 32; + cl = (cl) & 0xffffffff; + printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[0]) >> 32; + al = (regs->regs[0]) & 0xffffffff; + bh = (regs->regs[1]) >> 32; + bl = (regs->regs[1]) & 0xffffffff; + ch = (regs->regs[2]) >> 32; + cl = (regs->regs[2]) & 0xffffffff; + printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[3]) >> 32; + al = (regs->regs[3]) & 0xffffffff; + bh = (regs->regs[4]) >> 32; + bl = (regs->regs[4]) & 0xffffffff; + ch = (regs->regs[5]) >> 32; + cl = (regs->regs[5]) & 0xffffffff; + printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[6]) >> 32; + al = (regs->regs[6]) & 0xffffffff; + bh = (regs->regs[7]) >> 32; + bl = (regs->regs[7]) & 0xffffffff; + ch = (regs->regs[8]) >> 32; + cl = (regs->regs[8]) & 0xffffffff; + printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[9]) >> 32; + al = (regs->regs[9]) & 0xffffffff; + bh = (regs->regs[10]) >> 32; + bl = (regs->regs[10]) & 0xffffffff; + ch = (regs->regs[11]) >> 32; + cl = (regs->regs[11]) & 0xffffffff; + printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[12]) >> 32; + al = (regs->regs[12]) & 0xffffffff; + bh = (regs->regs[13]) >> 32; + bl = (regs->regs[13]) & 0xffffffff; + ch = (regs->regs[14]) >> 32; + cl = (regs->regs[14]) & 0xffffffff; + printk("R12 : %08Lx%08Lx R13 : %08Lx%08Lx R14 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[16]) >> 32; + al = (regs->regs[16]) & 0xffffffff; + bh = (regs->regs[17]) >> 32; + bl = (regs->regs[17]) & 0xffffffff; + ch = (regs->regs[19]) >> 32; + cl = (regs->regs[19]) & 0xffffffff; + printk("R16 : %08Lx%08Lx R17 : %08Lx%08Lx R19 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[20]) >> 32; + al = (regs->regs[20]) & 0xffffffff; + bh = (regs->regs[21]) >> 32; + bl = (regs->regs[21]) & 0xffffffff; + ch = (regs->regs[22]) >> 32; + cl = (regs->regs[22]) & 0xffffffff; + printk("R20 : %08Lx%08Lx R21 : %08Lx%08Lx R22 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[23]) >> 32; + al = (regs->regs[23]) & 0xffffffff; + bh = (regs->regs[24]) >> 32; + bl = (regs->regs[24]) & 0xffffffff; + ch = (regs->regs[25]) >> 32; + cl = (regs->regs[25]) & 0xffffffff; + printk("R23 : %08Lx%08Lx R24 : %08Lx%08Lx R25 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[26]) >> 32; + al = (regs->regs[26]) & 0xffffffff; + bh = (regs->regs[27]) >> 32; + bl = (regs->regs[27]) & 0xffffffff; + ch = (regs->regs[28]) >> 32; + cl = (regs->regs[28]) & 0xffffffff; + printk("R26 : %08Lx%08Lx R27 : %08Lx%08Lx R28 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[29]) >> 32; + al = (regs->regs[29]) & 0xffffffff; + bh = (regs->regs[30]) >> 32; + bl = (regs->regs[30]) & 0xffffffff; + ch = (regs->regs[31]) >> 32; + cl = (regs->regs[31]) & 0xffffffff; + printk("R29 : %08Lx%08Lx R30 : %08Lx%08Lx R31 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[32]) >> 32; + al = (regs->regs[32]) & 0xffffffff; + bh = (regs->regs[33]) >> 32; + bl = (regs->regs[33]) & 0xffffffff; + ch = (regs->regs[34]) >> 32; + cl = (regs->regs[34]) & 0xffffffff; + printk("R32 : %08Lx%08Lx R33 : %08Lx%08Lx R34 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[35]) >> 32; + al = (regs->regs[35]) & 0xffffffff; + bh = (regs->regs[36]) >> 32; + bl = (regs->regs[36]) & 0xffffffff; + ch = (regs->regs[37]) >> 32; + cl = (regs->regs[37]) & 0xffffffff; + printk("R35 : %08Lx%08Lx R36 : %08Lx%08Lx R37 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[38]) >> 32; + al = (regs->regs[38]) & 0xffffffff; + bh = (regs->regs[39]) >> 32; + bl = (regs->regs[39]) & 0xffffffff; + ch = (regs->regs[40]) >> 32; + cl = (regs->regs[40]) & 0xffffffff; + printk("R38 : %08Lx%08Lx R39 : %08Lx%08Lx R40 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[41]) >> 32; + al = (regs->regs[41]) & 0xffffffff; + bh = (regs->regs[42]) >> 32; + bl = (regs->regs[42]) & 0xffffffff; + ch = (regs->regs[43]) >> 32; + cl = (regs->regs[43]) & 0xffffffff; + printk("R41 : %08Lx%08Lx R42 : %08Lx%08Lx R43 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[44]) >> 32; + al = (regs->regs[44]) & 0xffffffff; + bh = (regs->regs[45]) >> 32; + bl = (regs->regs[45]) & 0xffffffff; + ch = (regs->regs[46]) >> 32; + cl = (regs->regs[46]) & 0xffffffff; + printk("R44 : %08Lx%08Lx R45 : %08Lx%08Lx R46 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[47]) >> 32; + al = (regs->regs[47]) & 0xffffffff; + bh = (regs->regs[48]) >> 32; + bl = (regs->regs[48]) & 0xffffffff; + ch = (regs->regs[49]) >> 32; + cl = (regs->regs[49]) & 0xffffffff; + printk("R47 : %08Lx%08Lx R48 : %08Lx%08Lx R49 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[50]) >> 32; + al = (regs->regs[50]) & 0xffffffff; + bh = (regs->regs[51]) >> 32; + bl = (regs->regs[51]) & 0xffffffff; + ch = (regs->regs[52]) >> 32; + cl = (regs->regs[52]) & 0xffffffff; + printk("R50 : %08Lx%08Lx R51 : %08Lx%08Lx R52 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[53]) >> 32; + al = (regs->regs[53]) & 0xffffffff; + bh = (regs->regs[54]) >> 32; + bl = (regs->regs[54]) & 0xffffffff; + ch = (regs->regs[55]) >> 32; + cl = (regs->regs[55]) & 0xffffffff; + printk("R53 : %08Lx%08Lx R54 : %08Lx%08Lx R55 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[56]) >> 32; + al = (regs->regs[56]) & 0xffffffff; + bh = (regs->regs[57]) >> 32; + bl = (regs->regs[57]) & 0xffffffff; + ch = (regs->regs[58]) >> 32; + cl = (regs->regs[58]) & 0xffffffff; + printk("R56 : %08Lx%08Lx R57 : %08Lx%08Lx R58 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[59]) >> 32; + al = (regs->regs[59]) & 0xffffffff; + bh = (regs->regs[60]) >> 32; + bl = (regs->regs[60]) & 0xffffffff; + ch = (regs->regs[61]) >> 32; + cl = (regs->regs[61]) & 0xffffffff; + printk("R59 : %08Lx%08Lx R60 : %08Lx%08Lx R61 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[62]) >> 32; + al = (regs->regs[62]) & 0xffffffff; + bh = (regs->tregs[0]) >> 32; + bl = (regs->tregs[0]) & 0xffffffff; + ch = (regs->tregs[1]) >> 32; + cl = (regs->tregs[1]) & 0xffffffff; + printk("R62 : %08Lx%08Lx T0 : %08Lx%08Lx T1 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->tregs[2]) >> 32; + al = (regs->tregs[2]) & 0xffffffff; + bh = (regs->tregs[3]) >> 32; + bl = (regs->tregs[3]) & 0xffffffff; + ch = (regs->tregs[4]) >> 32; + cl = (regs->tregs[4]) & 0xffffffff; + printk("T2 : %08Lx%08Lx T3 : %08Lx%08Lx T4 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->tregs[5]) >> 32; + al = (regs->tregs[5]) & 0xffffffff; + bh = (regs->tregs[6]) >> 32; + bl = (regs->tregs[6]) & 0xffffffff; + ch = (regs->tregs[7]) >> 32; + cl = (regs->tregs[7]) & 0xffffffff; + printk("T5 : %08Lx%08Lx T6 : %08Lx%08Lx T7 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + /* + * If we're in kernel mode, dump the stack too.. + */ + if (!user_mode(regs)) { + void show_stack(struct task_struct *tsk, unsigned long *sp); + unsigned long sp = regs->regs[15] & 0xffffffff; + struct task_struct *tsk = get_current(); + + tsk->thread.kregs = regs; + + show_stack(tsk, (unsigned long *)sp); + } +} + +struct task_struct * alloc_task_struct(void) +{ + /* Get task descriptor pages */ + return (struct task_struct *) + __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); +} + +void free_task_struct(struct task_struct *p) +{ + free_pages((unsigned long) p, get_order(THREAD_SIZE)); +} + +/* + * Create a kernel thread + */ +ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) +{ + do_exit(fn(arg)); +} + +/* + * This is the mechanism for creating a new kernel thread. + * + * NOTE! Only a kernel-only process(ie the swapper or direct descendants + * who haven't done an "execve()") should use this: it will work within + * a system call from a "real" process, but the process memory space will + * not be freed until both the parent and the child have exited. + */ +int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) +{ + struct pt_regs regs; + + memset(®s, 0, sizeof(regs)); + regs.regs[2] = (unsigned long)arg; + regs.regs[3] = (unsigned long)fn; + + regs.pc = (unsigned long)kernel_thread_helper; + regs.sr = (1 << 30); + + return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, + ®s, 0, NULL, NULL); +} + +/* + * Free current thread data structures etc.. + */ +void exit_thread(void) +{ + /* + * See arch/sparc/kernel/process.c for the precedent for doing + * this -- RPC. + * + * The SH-5 FPU save/restore approach relies on + * last_task_used_math pointing to a live task_struct. When + * another task tries to use the FPU for the 1st time, the FPUDIS + * trap handling (see arch/sh/kernel/cpu/sh5/fpu.c) will save the + * existing FPU state to the FP regs field within + * last_task_used_math before re-loading the new task's FPU state + * (or initialising it if the FPU has been used before). So if + * last_task_used_math is stale, and its page has already been + * re-allocated for another use, the consequences are rather + * grim. Unless we null it here, there is no other path through + * which it would get safely nulled. + */ +#ifdef CONFIG_SH_FPU + if (last_task_used_math == current) { + last_task_used_math = NULL; + } +#endif +} + +void flush_thread(void) +{ + + /* Called by fs/exec.c (flush_old_exec) to remove traces of a + * previously running executable. */ +#ifdef CONFIG_SH_FPU + if (last_task_used_math == current) { + last_task_used_math = NULL; + } + /* Force FPU state to be reinitialised after exec */ + clear_used_math(); +#endif + + /* if we are a kernel thread, about to change to user thread, + * update kreg + */ + if(current->thread.kregs==&fake_swapper_regs) { + current->thread.kregs = + ((struct pt_regs *)(THREAD_SIZE + (unsigned long) current) - 1); + current->thread.uregs = current->thread.kregs; + } +} + +void release_thread(struct task_struct *dead_task) +{ + /* do nothing */ +} + +/* Fill in the fpu structure for a core dump.. */ +int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) +{ +#ifdef CONFIG_SH_FPU + int fpvalid; + struct task_struct *tsk = current; + + fpvalid = !!tsk_used_math(tsk); + if (fpvalid) { + if (current == last_task_used_math) { + enable_fpu(); + save_fpu(tsk, regs); + disable_fpu(); + last_task_used_math = 0; + regs->sr |= SR_FD; + } + + memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); + } + + return fpvalid; +#else + return 0; /* Task didn't use the fpu at all. */ +#endif +} + +asmlinkage void ret_from_fork(void); + +int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, + unsigned long unused, + struct task_struct *p, struct pt_regs *regs) +{ + struct pt_regs *childregs; + unsigned long long se; /* Sign extension */ + +#ifdef CONFIG_SH_FPU + if(last_task_used_math == current) { + enable_fpu(); + save_fpu(current, regs); + disable_fpu(); + last_task_used_math = NULL; + regs->sr |= SR_FD; + } +#endif + /* Copy from sh version */ + childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; + + *childregs = *regs; + + if (user_mode(regs)) { + childregs->regs[15] = usp; + p->thread.uregs = childregs; + } else { + childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; + } + + childregs->regs[9] = 0; /* Set return value for child */ + childregs->sr |= SR_FD; /* Invalidate FPU flag */ + + p->thread.sp = (unsigned long) childregs; + p->thread.pc = (unsigned long) ret_from_fork; + + /* + * Sign extend the edited stack. + * Note that thread.pc and thread.pc will stay + * 32-bit wide and context switch must take care + * of NEFF sign extension. + */ + + se = childregs->regs[15]; + se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se; + childregs->regs[15] = se; + + return 0; +} + +asmlinkage int sys_fork(unsigned long r2, unsigned long r3, + unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs *pregs) +{ + return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); +} + +asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, + unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs *pregs) +{ + if (!newsp) + newsp = pregs->regs[15]; + return do_fork(clone_flags, newsp, pregs, 0, 0, 0); +} + +/* + * This is trivial, and on the face of it looks like it + * could equally well be done in user mode. + * + * Not so, for quite unobvious reasons - register pressure. + * In user mode vfork() cannot have a stack frame, and if + * done by calling the "clone()" system call directly, you + * do not have enough call-clobbered registers to hold all + * the information you need. + */ +asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, + unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs *pregs) +{ + return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); +} + +/* + * sys_execve() executes a new program. + */ +asmlinkage int sys_execve(char *ufilename, char **uargv, + char **uenvp, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs *pregs) +{ + int error; + char *filename; + + lock_kernel(); + filename = getname((char __user *)ufilename); + error = PTR_ERR(filename); + if (IS_ERR(filename)) + goto out; + + error = do_execve(filename, + (char __user * __user *)uargv, + (char __user * __user *)uenvp, + pregs); + if (error == 0) { + task_lock(current); + current->ptrace &= ~PT_DTRACE; + task_unlock(current); + } + putname(filename); +out: + unlock_kernel(); + return error; +} + +/* + * These bracket the sleeping functions.. + */ +extern void interruptible_sleep_on(wait_queue_head_t *q); + +#define mid_sched ((unsigned long) interruptible_sleep_on) + +static int in_sh64_switch_to(unsigned long pc) +{ + extern char __sh64_switch_to_end; + /* For a sleeping task, the PC is somewhere in the middle of the function, + so we don't have to worry about masking the LSB off */ + return (pc >= (unsigned long) sh64_switch_to) && + (pc < (unsigned long) &__sh64_switch_to_end); +} + +unsigned long get_wchan(struct task_struct *p) +{ + unsigned long schedule_fp; + unsigned long sh64_switch_to_fp; + unsigned long schedule_caller_pc; + unsigned long pc; + + if (!p || p == current || p->state == TASK_RUNNING) + return 0; + + /* + * The same comment as on the Alpha applies here, too ... + */ + pc = thread_saved_pc(p); + +#ifdef CONFIG_FRAME_POINTER + if (in_sh64_switch_to(pc)) { + sh64_switch_to_fp = (long) p->thread.sp; + /* r14 is saved at offset 4 in the sh64_switch_to frame */ + schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); + + /* and the caller of 'schedule' is (currently!) saved at offset 24 + in the frame of schedule (from disasm) */ + schedule_caller_pc = *(unsigned long *) (long)(schedule_fp + 24); + return schedule_caller_pc; + } +#endif + return pc; +} + +/* Provide a /proc/asids file that lists out the + ASIDs currently associated with the processes. (If the DM.PC register is + examined through the debug link, this shows ASID + PC. To make use of this, + the PID->ASID relationship needs to be known. This is primarily for + debugging.) + */ + +#if defined(CONFIG_SH64_PROC_ASIDS) +static int +asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) +{ + int len=0; + struct task_struct *p; + read_lock(&tasklist_lock); + for_each_process(p) { + int pid = p->pid; + + if (!pid) + continue; + if (p->mm) + len += sprintf(buf+len, "%5d : %02lx\n", pid, + asid_cache(smp_processor_id())); + else + len += sprintf(buf+len, "%5d : (none)\n", pid); + } + read_unlock(&tasklist_lock); + *eof = 1; + return len; +} + +static int __init register_proc_asids(void) +{ + create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); + return 0; +} +__initcall(register_proc_asids); +#endif diff -puN arch/sh/kernel/ptrace.c~git-sh /dev/null --- a/arch/sh/kernel/ptrace.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * linux/arch/sh/kernel/ptrace.c - * - * Original x86 implementation: - * By Ross Biro 1/23/92 - * edited by Linus Torvalds - * - * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* - * This routine will get a word off of the process kernel stack. - */ -static inline int get_stack_long(struct task_struct *task, int offset) -{ - unsigned char *stack; - - stack = (unsigned char *)task_pt_regs(task); - stack += offset; - return (*((int *)stack)); -} - -/* - * This routine will put a word on the process kernel stack. - */ -static inline int put_stack_long(struct task_struct *task, int offset, - unsigned long data) -{ - unsigned char *stack; - - stack = (unsigned char *)task_pt_regs(task); - stack += offset; - *(unsigned long *) stack = data; - return 0; -} - -static void ptrace_disable_singlestep(struct task_struct *child) -{ - clear_tsk_thread_flag(child, TIF_SINGLESTEP); - - /* - * Ensure the UBC is not programmed at the next context switch. - * - * Normally this is not needed but there are sequences such as - * singlestep, signal delivery, and continue that leave the - * ubc_pc non-zero leading to spurious SIGTRAPs. - */ - if (child->thread.ubc_pc != 0) { - ubc_usercnt -= 1; - child->thread.ubc_pc = 0; - } -} - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - ptrace_disable_singlestep(child); -} - -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - struct user * dummy = NULL; - int ret; - - 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: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - break; - - if (addr < sizeof(struct pt_regs)) - tmp = get_stack_long(child, addr); - else if (addr >= (long) &dummy->fpu && - addr < (long) &dummy->u_fpvalid) { - if (!tsk_used_math(child)) { - if (addr == (long)&dummy->fpu.fpscr) - tmp = FPSCR_INIT; - else - tmp = 0; - } else - tmp = ((long *)&child->thread.fpu) - [(addr - (long)&dummy->fpu) >> 2]; - } else if (addr == (long) &dummy->u_fpvalid) - tmp = !!tsk_used_math(child); - else - tmp = 0; - ret = put_user(tmp, (unsigned long __user *)data); - 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 = generic_ptrace_pokedata(child, addr, data); - break; - - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ - ret = -EIO; - if ((addr & 3) || addr < 0 || - addr > sizeof(struct user) - 3) - break; - - if (addr < sizeof(struct pt_regs)) - ret = put_stack_long(child, addr, data); - else if (addr >= (long) &dummy->fpu && - addr < (long) &dummy->u_fpvalid) { - set_stopped_child_used_math(child); - ((long *)&child->thread.fpu) - [(addr - (long)&dummy->fpu) >> 2] = data; - ret = 0; - } else if (addr == (long) &dummy->u_fpvalid) { - conditional_stopped_child_used_math(data, child); - ret = 0; - } - 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); - - ptrace_disable_singlestep(child); - - child->exit_code = data; - 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 */ - break; - ptrace_disable_singlestep(child); - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long pc; - struct pt_regs *regs = NULL; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - pc = get_stack_long(child, (long)®s->pc); - - /* Next scheduling will set up UBC */ - if (child->thread.ubc_pc == 0) - ubc_usercnt += 1; - child->thread.ubc_pc = pc; - - set_tsk_thread_flag(child, TIF_SINGLESTEP); - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - -#ifdef CONFIG_SH_DSP - case PTRACE_GETDSPREGS: { - unsigned long dp; - - ret = -EIO; - dp = ((unsigned long) child) + THREAD_SIZE - - sizeof(struct pt_dspregs); - if (*((int *) (dp - 4)) == SR_FD) { - copy_to_user(addr, (void *) dp, - sizeof(struct pt_dspregs)); - ret = 0; - } - break; - } - - case PTRACE_SETDSPREGS: { - unsigned long dp; - - ret = -EIO; - dp = ((unsigned long) child) + THREAD_SIZE - - sizeof(struct pt_dspregs); - if (*((int *) (dp - 4)) == SR_FD) { - copy_from_user((void *) dp, addr, - sizeof(struct pt_dspregs)); - ret = 0; - } - break; - } -#endif - default: - ret = ptrace_request(child, request, addr, data); - break; - } - - return ret; -} - -asmlinkage void do_syscall_trace(void) -{ - struct task_struct *tsk = current; - - if (!test_thread_flag(TIF_SYSCALL_TRACE) && - !test_thread_flag(TIF_SINGLESTEP)) - return; - if (!(tsk->ptrace & PT_PTRACED)) - return; - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && - !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); - - /* - * 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 (tsk->exit_code) { - send_sig(tsk->exit_code, tsk, 1); - tsk->exit_code = 0; - } -} diff -puN /dev/null arch/sh/kernel/ptrace_32.c --- /dev/null +++ a/arch/sh/kernel/ptrace_32.c @@ -0,0 +1,287 @@ +/* + * linux/arch/sh/kernel/ptrace.c + * + * Original x86 implementation: + * By Ross Biro 1/23/92 + * edited by Linus Torvalds + * + * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * Audit support: Yuichi Nakamura + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. + */ + +/* + * This routine will get a word off of the process kernel stack. + */ +static inline int get_stack_long(struct task_struct *task, int offset) +{ + unsigned char *stack; + + stack = (unsigned char *)task_pt_regs(task); + stack += offset; + return (*((int *)stack)); +} + +/* + * This routine will put a word on the process kernel stack. + */ +static inline int put_stack_long(struct task_struct *task, int offset, + unsigned long data) +{ + unsigned char *stack; + + stack = (unsigned char *)task_pt_regs(task); + stack += offset; + *(unsigned long *) stack = data; + return 0; +} + +static void ptrace_disable_singlestep(struct task_struct *child) +{ + clear_tsk_thread_flag(child, TIF_SINGLESTEP); + + /* + * Ensure the UBC is not programmed at the next context switch. + * + * Normally this is not needed but there are sequences such as + * singlestep, signal delivery, and continue that leave the + * ubc_pc non-zero leading to spurious SIGTRAPs. + */ + if (child->thread.ubc_pc != 0) { + ubc_usercnt -= 1; + child->thread.ubc_pc = 0; + } +} + +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + ptrace_disable_singlestep(child); +} + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + struct user * dummy = NULL; + int ret; + + 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: + ret = generic_ptrace_peekdata(child, addr, data); + break; + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: { + unsigned long tmp; + + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; + + if (addr < sizeof(struct pt_regs)) + tmp = get_stack_long(child, addr); + else if (addr >= (long) &dummy->fpu && + addr < (long) &dummy->u_fpvalid) { + if (!tsk_used_math(child)) { + if (addr == (long)&dummy->fpu.fpscr) + tmp = FPSCR_INIT; + else + tmp = 0; + } else + tmp = ((long *)&child->thread.fpu) + [(addr - (long)&dummy->fpu) >> 2]; + } else if (addr == (long) &dummy->u_fpvalid) + tmp = !!tsk_used_math(child); + else + tmp = 0; + ret = put_user(tmp, (unsigned long __user *)data); + 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 = generic_ptrace_pokedata(child, addr, data); + break; + + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ + ret = -EIO; + if ((addr & 3) || addr < 0 || + addr > sizeof(struct user) - 3) + break; + + if (addr < sizeof(struct pt_regs)) + ret = put_stack_long(child, addr, data); + else if (addr >= (long) &dummy->fpu && + addr < (long) &dummy->u_fpvalid) { + set_stopped_child_used_math(child); + ((long *)&child->thread.fpu) + [(addr - (long)&dummy->fpu) >> 2] = data; + ret = 0; + } else if (addr == (long) &dummy->u_fpvalid) { + conditional_stopped_child_used_math(data, child); + ret = 0; + } + 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); + + ptrace_disable_singlestep(child); + + child->exit_code = data; + 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 */ + break; + ptrace_disable_singlestep(child); + child->exit_code = SIGKILL; + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + long pc; + struct pt_regs *regs = NULL; + + ret = -EIO; + if (!valid_signal(data)) + break; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + if ((child->ptrace & PT_DTRACE) == 0) { + /* Spurious delayed TF traps may occur */ + child->ptrace |= PT_DTRACE; + } + + pc = get_stack_long(child, (long)®s->pc); + + /* Next scheduling will set up UBC */ + if (child->thread.ubc_pc == 0) + ubc_usercnt += 1; + child->thread.ubc_pc = pc; + + set_tsk_thread_flag(child, TIF_SINGLESTEP); + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } + +#ifdef CONFIG_SH_DSP + case PTRACE_GETDSPREGS: { + unsigned long dp; + + ret = -EIO; + dp = ((unsigned long) child) + THREAD_SIZE - + sizeof(struct pt_dspregs); + if (*((int *) (dp - 4)) == SR_FD) { + copy_to_user(addr, (void *) dp, + sizeof(struct pt_dspregs)); + ret = 0; + } + break; + } + + case PTRACE_SETDSPREGS: { + unsigned long dp; + + ret = -EIO; + dp = ((unsigned long) child) + THREAD_SIZE - + sizeof(struct pt_dspregs); + if (*((int *) (dp - 4)) == SR_FD) { + copy_from_user((void *) dp, addr, + sizeof(struct pt_dspregs)); + ret = 0; + } + break; + } +#endif + default: + ret = ptrace_request(child, request, addr, data); + break; + } + + return ret; +} + +asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) +{ + struct task_struct *tsk = current; + + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), + regs->regs[0]); + + if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SINGLESTEP)) + goto out; + if (!(tsk->ptrace & PT_PTRACED)) + goto out; + + /* the 0x80 provides a way for the tracing parent to distinguish + between a syscall stop and SIGTRAP delivery */ + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && + !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); + + /* + * 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 (tsk->exit_code) { + send_sig(tsk->exit_code, tsk, 1); + tsk->exit_code = 0; + } + +out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3], + regs->regs[4], regs->regs[5], + regs->regs[6], regs->regs[7]); + +} diff -puN /dev/null arch/sh/kernel/ptrace_64.c --- /dev/null +++ a/arch/sh/kernel/ptrace_64.c @@ -0,0 +1,341 @@ +/* + * arch/sh/kernel/ptrace_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * + * Started from SH3/4 version: + * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka + * + * Original x86 implementation: + * By Ross Biro 1/23/92 + * edited by Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* This mask defines the bits of the SR which the user is not allowed to + change, which are everything except S, Q, M, PR, SZ, FR. */ +#define SR_MASK (0xffff8cfd) + +/* + * does not yet catch signals sent when the child dies. + * in exit.c or in signal.c. + */ + +/* + * This routine will get a word from the user area in the process kernel stack. + */ +static inline int get_stack_long(struct task_struct *task, int offset) +{ + unsigned char *stack; + + stack = (unsigned char *)(task->thread.uregs); + stack += offset; + return (*((int *)stack)); +} + +static inline unsigned long +get_fpu_long(struct task_struct *task, unsigned long addr) +{ + unsigned long tmp; + struct pt_regs *regs; + regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; + + if (!tsk_used_math(task)) { + if (addr == offsetof(struct user_fpu_struct, fpscr)) { + tmp = FPSCR_INIT; + } else { + tmp = 0xffffffffUL; /* matches initial value in fpu.c */ + } + return tmp; + } + + if (last_task_used_math == task) { + enable_fpu(); + save_fpu(task, regs); + disable_fpu(); + last_task_used_math = 0; + regs->sr |= SR_FD; + } + + tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)]; + return tmp; +} + +/* + * This routine will put a word into the user area in the process kernel stack. + */ +static inline int put_stack_long(struct task_struct *task, int offset, + unsigned long data) +{ + unsigned char *stack; + + stack = (unsigned char *)(task->thread.uregs); + stack += offset; + *(unsigned long *) stack = data; + return 0; +} + +static inline int +put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) +{ + struct pt_regs *regs; + + regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; + + if (!tsk_used_math(task)) { + fpinit(&task->thread.fpu.hard); + set_stopped_child_used_math(task); + } else if (last_task_used_math == task) { + enable_fpu(); + save_fpu(task, regs); + disable_fpu(); + last_task_used_math = 0; + regs->sr |= SR_FD; + } + + ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data; + return 0; +} + + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) +{ + int ret; + + 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: + ret = generic_ptrace_peekdata(child, addr, data); + break; + + /* read the word at location addr in the USER area. */ + case PTRACE_PEEKUSR: { + unsigned long tmp; + + ret = -EIO; + if ((addr & 3) || addr < 0) + break; + + if (addr < sizeof(struct pt_regs)) + tmp = get_stack_long(child, addr); + else if ((addr >= offsetof(struct user, fpu)) && + (addr < offsetof(struct user, u_fpvalid))) { + tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); + } else if (addr == offsetof(struct user, u_fpvalid)) { + tmp = !!tsk_used_math(child); + } else { + break; + } + ret = put_user(tmp, (unsigned long *)data); + 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 = generic_ptrace_pokedata(child, addr, data); + break; + + case PTRACE_POKEUSR: + /* write the word at location addr in the USER area. We must + disallow any changes to certain SR bits or u_fpvalid, since + this could crash the kernel or result in a security + loophole. */ + ret = -EIO; + if ((addr & 3) || addr < 0) + break; + + if (addr < sizeof(struct pt_regs)) { + /* Ignore change of top 32 bits of SR */ + if (addr == offsetof (struct pt_regs, sr)+4) + { + ret = 0; + break; + } + /* If lower 32 bits of SR, ignore non-user bits */ + if (addr == offsetof (struct pt_regs, sr)) + { + long cursr = get_stack_long(child, addr); + data &= ~(SR_MASK); + data |= (cursr & SR_MASK); + } + ret = put_stack_long(child, addr, data); + } + else if ((addr >= offsetof(struct user, fpu)) && + (addr < offsetof(struct user, u_fpvalid))) { + ret = put_fpu_long(child, addr - offsetof(struct user, fpu), data); + } + 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; + 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 */ + break; + child->exit_code = SIGKILL; + wake_up_process(child); + break; + } + + case PTRACE_SINGLESTEP: { /* set the trap flag. */ + struct pt_regs *regs; + + ret = -EIO; + if (!valid_signal(data)) + break; + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + if ((child->ptrace & PT_DTRACE) == 0) { + /* Spurious delayed TF traps may occur */ + child->ptrace |= PT_DTRACE; + } + + regs = child->thread.uregs; + + regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ + + child->exit_code = data; + /* give it a chance to run. */ + wake_up_process(child); + ret = 0; + break; + } + + default: + ret = ptrace_request(child, request, addr, data); + break; + } + return ret; +} + +asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) +{ +#define WPC_DBRMODE 0x0d104008 + static int first_call = 1; + + lock_kernel(); + if (first_call) { + /* Set WPC.DBRMODE to 0. This makes all debug events get + * delivered through RESVEC, i.e. into the handlers in entry.S. + * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE + * would normally be left set to 1, which makes debug events get + * delivered through DBRVEC, i.e. into the remote gdb's + * handlers. This prevents ptrace getting them, and confuses + * the remote gdb.) */ + printk("DBRMODE set to 0 to permit native debugging\n"); + poke_real_address_q(WPC_DBRMODE, 0); + first_call = 0; + } + unlock_kernel(); + + return sys_ptrace(request, pid, addr, data); +} + +asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) +{ + struct task_struct *tsk = current; + + if (unlikely(current->audit_context) && entryexit) + audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), + regs->regs[9]); + + if (!test_thread_flag(TIF_SYSCALL_TRACE) && + !test_thread_flag(TIF_SINGLESTEP)) + goto out; + if (!(tsk->ptrace & PT_PTRACED)) + goto out; + + ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && + !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); + + /* + * 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 (tsk->exit_code) { + send_sig(tsk->exit_code, tsk, 1); + tsk->exit_code = 0; + } + +out: + if (unlikely(current->audit_context) && !entryexit) + audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], + regs->regs[2], regs->regs[3], + regs->regs[4], regs->regs[5]); +} + +/* Called with interrupts disabled */ +asmlinkage void do_single_step(unsigned long long vec, struct pt_regs *regs) +{ + /* This is called after a single step exception (DEBUGSS). + There is no need to change the PC, as it is a post-execution + exception, as entry.S does not do anything to the PC for DEBUGSS. + We need to clear the Single Step setting in SR to avoid + continually stepping. */ + local_irq_enable(); + regs->sr &= ~SR_SSTEP; + force_sig(SIGTRAP, current); +} + +/* Called with interrupts disabled */ +asmlinkage void do_software_break_point(unsigned long long vec, + struct pt_regs *regs) +{ + /* We need to forward step the PC, to counteract the backstep done + in signal.c. */ + local_irq_enable(); + force_sig(SIGTRAP, current); + regs->pc += 4; +} + +/* + * Called by kernel/ptrace.c when detaching.. + * + * Make sure single step bits etc are not set. + */ +void ptrace_disable(struct task_struct *child) +{ + /* nothing to do.. */ +} diff -puN arch/sh/kernel/setup.c~git-sh arch/sh/kernel/setup.c --- a/arch/sh/kernel/setup.c~git-sh +++ a/arch/sh/kernel/setup.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -78,12 +79,25 @@ EXPORT_SYMBOL(memory_start); unsigned long memory_end = 0; EXPORT_SYMBOL(memory_end); +int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; + static int __init early_parse_mem(char *p) { unsigned long size; - memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; + memory_start = (unsigned long)__va(__MEMORY_START); size = memparse(p, &p); + + if (size > __MEMORY_SIZE) { + static char msg[] __initdata = KERN_ERR + "Using mem= to increase the size of kernel memory " + "is not allowed.\n" + " Recompile the kernel with the correct value for " + "CONFIG_MEMORY_SIZE.\n"; + printk(msg); + return 0; + } + memory_end = memory_start + size; return 0; @@ -243,7 +257,7 @@ void __init setup_arch(char **cmdline_p) data_resource.start = virt_to_phys(_etext); data_resource.end = virt_to_phys(_edata)-1; - memory_start = (unsigned long)PAGE_OFFSET+__MEMORY_START; + memory_start = (unsigned long)__va(__MEMORY_START); if (!memory_end) memory_end = memory_start + __MEMORY_SIZE; @@ -294,6 +308,7 @@ void __init setup_arch(char **cmdline_p) } static const char *cpu_name[] = { + [CPU_SH7203] = "SH7203", [CPU_SH7263] = "SH7263", [CPU_SH7206] = "SH7206", [CPU_SH7619] = "SH7619", [CPU_SH7705] = "SH7705", [CPU_SH7706] = "SH7706", [CPU_SH7707] = "SH7707", [CPU_SH7708] = "SH7708", @@ -307,7 +322,9 @@ static const char *cpu_name[] = { [CPU_SH7770] = "SH7770", [CPU_SH7780] = "SH7780", [CPU_SH7781] = "SH7781", [CPU_SH7343] = "SH7343", [CPU_SH7785] = "SH7785", [CPU_SH7722] = "SH7722", - [CPU_SHX3] = "SH-X3", [CPU_SH_NONE] = "Unknown" + [CPU_SHX3] = "SH-X3", + [CPU_SH5_101] = "SH5-101", [CPU_SH5_103] = "SH5-103", + [CPU_SH_NONE] = "Unknown" }; const char *get_cpu_subtype(struct sh_cpuinfo *c) diff -puN arch/sh/kernel/sh_ksyms.c~git-sh /dev/null --- a/arch/sh/kernel/sh_ksyms.c +++ /dev/null @@ -1,150 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); -extern struct hw_interrupt_type no_irq_type; - -EXPORT_SYMBOL(sh_mv); - -/* platform dependent support */ -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(kernel_thread); -EXPORT_SYMBOL(irq_desc); -EXPORT_SYMBOL(no_irq_type); - -EXPORT_SYMBOL(strlen); - -/* PCI exports */ -#ifdef CONFIG_PCI -EXPORT_SYMBOL(pci_alloc_consistent); -EXPORT_SYMBOL(pci_free_consistent); -#endif - -/* mem exports */ -EXPORT_SYMBOL(memchr); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); -EXPORT_SYMBOL(memmove); -EXPORT_SYMBOL(__copy_user); - -#ifdef CONFIG_MMU -EXPORT_SYMBOL(get_vm_area); -#endif - -/* semaphore exports */ -EXPORT_SYMBOL(__up); -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_interruptible); -EXPORT_SYMBOL(__down_trylock); - -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(__const_udelay); - -#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) - -/* These symbols are generated by the compiler itself */ -DECLARE_EXPORT(__udivsi3); -DECLARE_EXPORT(__sdivsi3); -DECLARE_EXPORT(__ashrsi3); -DECLARE_EXPORT(__ashlsi3); -DECLARE_EXPORT(__ashrdi3); -DECLARE_EXPORT(__ashldi3); -DECLARE_EXPORT(__ashiftrt_r4_6); -DECLARE_EXPORT(__ashiftrt_r4_7); -DECLARE_EXPORT(__ashiftrt_r4_8); -DECLARE_EXPORT(__ashiftrt_r4_9); -DECLARE_EXPORT(__ashiftrt_r4_10); -DECLARE_EXPORT(__ashiftrt_r4_11); -DECLARE_EXPORT(__ashiftrt_r4_12); -DECLARE_EXPORT(__ashiftrt_r4_13); -DECLARE_EXPORT(__ashiftrt_r4_14); -DECLARE_EXPORT(__ashiftrt_r4_15); -DECLARE_EXPORT(__ashiftrt_r4_20); -DECLARE_EXPORT(__ashiftrt_r4_21); -DECLARE_EXPORT(__ashiftrt_r4_22); -DECLARE_EXPORT(__ashiftrt_r4_23); -DECLARE_EXPORT(__ashiftrt_r4_24); -DECLARE_EXPORT(__ashiftrt_r4_27); -DECLARE_EXPORT(__ashiftrt_r4_30); -DECLARE_EXPORT(__lshrsi3); -DECLARE_EXPORT(__lshrdi3); -DECLARE_EXPORT(__movstrSI8); -DECLARE_EXPORT(__movstrSI12); -DECLARE_EXPORT(__movstrSI16); -DECLARE_EXPORT(__movstrSI20); -DECLARE_EXPORT(__movstrSI24); -DECLARE_EXPORT(__movstrSI28); -DECLARE_EXPORT(__movstrSI32); -DECLARE_EXPORT(__movstrSI36); -DECLARE_EXPORT(__movstrSI40); -DECLARE_EXPORT(__movstrSI44); -DECLARE_EXPORT(__movstrSI48); -DECLARE_EXPORT(__movstrSI52); -DECLARE_EXPORT(__movstrSI56); -DECLARE_EXPORT(__movstrSI60); -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem); -#else -DECLARE_EXPORT(__movstr); -#endif - -#if __GNUC__ == 4 -DECLARE_EXPORT(__movmem_i4_even); -DECLARE_EXPORT(__movmem_i4_odd); -DECLARE_EXPORT(__movmemSI12_i4); - -#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__)) -/* - * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST - * compiler which include backported patches. - */ -DECLARE_EXPORT(__sdivsi3_i4i); -DECLARE_EXPORT(__udiv_qrnnd_16); -DECLARE_EXPORT(__udivsi3_i4i); -#endif -#else /* GCC 3.x */ -DECLARE_EXPORT(__movstr_i4_even); -DECLARE_EXPORT(__movstr_i4_odd); -DECLARE_EXPORT(__movstrSI12_i4); -#endif /* __GNUC__ == 4 */ - -#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ - defined(CONFIG_SH7705_CACHE_32KB)) -/* needed by some modules */ -EXPORT_SYMBOL(flush_cache_all); -EXPORT_SYMBOL(flush_cache_range); -EXPORT_SYMBOL(flush_dcache_page); -EXPORT_SYMBOL(__flush_purge_region); -#endif - -#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ - (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) -EXPORT_SYMBOL(clear_user_page); -#endif - -EXPORT_SYMBOL(csum_partial); -EXPORT_SYMBOL(csum_partial_copy_generic); -#ifdef CONFIG_IPV6 -EXPORT_SYMBOL(csum_ipv6_magic); -#endif -EXPORT_SYMBOL(clear_page); -EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(_ebss); diff -puN /dev/null arch/sh/kernel/sh_ksyms_32.c --- /dev/null +++ a/arch/sh/kernel/sh_ksyms_32.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); +extern struct hw_interrupt_type no_irq_type; + +EXPORT_SYMBOL(sh_mv); + +/* platform dependent support */ +EXPORT_SYMBOL(dump_fpu); +EXPORT_SYMBOL(kernel_thread); +EXPORT_SYMBOL(irq_desc); +EXPORT_SYMBOL(no_irq_type); + +EXPORT_SYMBOL(strlen); + +/* PCI exports */ +#ifdef CONFIG_PCI +EXPORT_SYMBOL(pci_alloc_consistent); +EXPORT_SYMBOL(pci_free_consistent); +#endif + +/* mem exports */ +EXPORT_SYMBOL(memchr); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(memset); +EXPORT_SYMBOL(memmove); +EXPORT_SYMBOL(__copy_user); + +#ifdef CONFIG_MMU +EXPORT_SYMBOL(get_vm_area); +#endif + +/* semaphore exports */ +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_interruptible); +EXPORT_SYMBOL(__down_trylock); + +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__ndelay); +EXPORT_SYMBOL(__const_udelay); + +#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) + +/* These symbols are generated by the compiler itself */ +DECLARE_EXPORT(__udivsi3); +DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__ashrsi3); +DECLARE_EXPORT(__ashlsi3); +DECLARE_EXPORT(__ashrdi3); +DECLARE_EXPORT(__ashldi3); +DECLARE_EXPORT(__ashiftrt_r4_6); +DECLARE_EXPORT(__ashiftrt_r4_7); +DECLARE_EXPORT(__ashiftrt_r4_8); +DECLARE_EXPORT(__ashiftrt_r4_9); +DECLARE_EXPORT(__ashiftrt_r4_10); +DECLARE_EXPORT(__ashiftrt_r4_11); +DECLARE_EXPORT(__ashiftrt_r4_12); +DECLARE_EXPORT(__ashiftrt_r4_13); +DECLARE_EXPORT(__ashiftrt_r4_14); +DECLARE_EXPORT(__ashiftrt_r4_15); +DECLARE_EXPORT(__ashiftrt_r4_20); +DECLARE_EXPORT(__ashiftrt_r4_21); +DECLARE_EXPORT(__ashiftrt_r4_22); +DECLARE_EXPORT(__ashiftrt_r4_23); +DECLARE_EXPORT(__ashiftrt_r4_24); +DECLARE_EXPORT(__ashiftrt_r4_27); +DECLARE_EXPORT(__ashiftrt_r4_30); +DECLARE_EXPORT(__lshrsi3); +DECLARE_EXPORT(__lshrdi3); +DECLARE_EXPORT(__movstrSI8); +DECLARE_EXPORT(__movstrSI12); +DECLARE_EXPORT(__movstrSI16); +DECLARE_EXPORT(__movstrSI20); +DECLARE_EXPORT(__movstrSI24); +DECLARE_EXPORT(__movstrSI28); +DECLARE_EXPORT(__movstrSI32); +DECLARE_EXPORT(__movstrSI36); +DECLARE_EXPORT(__movstrSI40); +DECLARE_EXPORT(__movstrSI44); +DECLARE_EXPORT(__movstrSI48); +DECLARE_EXPORT(__movstrSI52); +DECLARE_EXPORT(__movstrSI56); +DECLARE_EXPORT(__movstrSI60); +#if __GNUC__ == 4 +DECLARE_EXPORT(__movmem); +#else +DECLARE_EXPORT(__movstr); +#endif + +#if __GNUC__ == 4 +DECLARE_EXPORT(__movmem_i4_even); +DECLARE_EXPORT(__movmem_i4_odd); +DECLARE_EXPORT(__movmemSI12_i4); + +#if (__GNUC_MINOR__ == 2 || defined(__GNUC_STM_RELEASE__)) +/* + * GCC 4.2 emits these for division, as do GCC 4.1.x versions of the ST + * compiler which include backported patches. + */ +DECLARE_EXPORT(__sdivsi3_i4i); +DECLARE_EXPORT(__udiv_qrnnd_16); +DECLARE_EXPORT(__udivsi3_i4i); +#endif +#else /* GCC 3.x */ +DECLARE_EXPORT(__movstr_i4_even); +DECLARE_EXPORT(__movstr_i4_odd); +DECLARE_EXPORT(__movstrSI12_i4); +#endif /* __GNUC__ == 4 */ + +#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ + defined(CONFIG_SH7705_CACHE_32KB)) +/* needed by some modules */ +EXPORT_SYMBOL(flush_cache_all); +EXPORT_SYMBOL(flush_cache_range); +EXPORT_SYMBOL(flush_dcache_page); +EXPORT_SYMBOL(__flush_purge_region); +#endif + +#if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ + (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) +EXPORT_SYMBOL(clear_user_page); +#endif + +EXPORT_SYMBOL(csum_partial); +EXPORT_SYMBOL(csum_partial_copy_generic); +#ifdef CONFIG_IPV6 +EXPORT_SYMBOL(csum_ipv6_magic); +#endif +EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(__clear_user); +EXPORT_SYMBOL(_ebss); diff -puN /dev/null arch/sh/kernel/sh_ksyms_64.c --- /dev/null +++ a/arch/sh/kernel/sh_ksyms_64.c @@ -0,0 +1,55 @@ +/* + * arch/sh/kernel/sh_ksyms_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); + +/* platform dependent support */ +EXPORT_SYMBOL(dump_fpu); +EXPORT_SYMBOL(kernel_thread); + +/* Networking helper routines. */ +EXPORT_SYMBOL(csum_partial_copy_nocheck); + +#ifdef CONFIG_VT +EXPORT_SYMBOL(screen_info); +#endif + +EXPORT_SYMBOL(__down); +EXPORT_SYMBOL(__down_trylock); +EXPORT_SYMBOL(__up); +EXPORT_SYMBOL(__put_user_asm_l); +EXPORT_SYMBOL(__get_user_asm_l); +EXPORT_SYMBOL(__copy_user); +EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(__udelay); +EXPORT_SYMBOL(__ndelay); + +/* Ugh. These come in from libgcc.a at link time. */ +#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) + +DECLARE_EXPORT(__sdivsi3); +DECLARE_EXPORT(__muldi3); +DECLARE_EXPORT(__udivsi3); diff -puN arch/sh/kernel/signal.c~git-sh /dev/null --- a/arch/sh/kernel/signal.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - * linux/arch/sh/kernel/signal.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson - * - * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ -asmlinkage int -sys_sigsuspend(old_sigset_t mask, - unsigned long r5, unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - 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, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - - return do_sigaltstack(uss, uoss, regs->regs[15]); -} - - -/* - * Do a signal return; undo the signal stack. - */ - -#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ -#if defined(CONFIG_CPU_SH2) -#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ -#else -#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ -#endif -#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ - -struct sigframe -{ - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; - u16 retcode[8]; -}; - -struct rt_sigframe -{ - struct siginfo info; - struct ucontext uc; - u16 retcode[8]; -}; - -#ifdef CONFIG_SH_FPU -static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) -{ - struct task_struct *tsk = current; - - if (!(current_cpu_data.flags & CPU_HAS_FPU)) - return 0; - - set_used_math(); - return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], - sizeof(long)*(16*2+2)); -} - -static inline int save_sigcontext_fpu(struct sigcontext __user *sc, - struct pt_regs *regs) -{ - struct task_struct *tsk = current; - - if (!(current_cpu_data.flags & CPU_HAS_FPU)) - return 0; - - if (!used_math()) { - __put_user(0, &sc->sc_ownedfp); - return 0; - } - - __put_user(1, &sc->sc_ownedfp); - - /* This will cause a "finit" to be triggered by the next - attempted FPU operation by the 'current' process. - */ - clear_used_math(); - - unlazy_fpu(tsk, regs); - return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, - sizeof(long)*(16*2+2)); -} -#endif /* CONFIG_SH_FPU */ - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p) -{ - unsigned int err = 0; - -#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) - COPY(regs[1]); - COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); - COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); - COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); - COPY(regs[14]); COPY(regs[15]); - COPY(gbr); COPY(mach); - COPY(macl); COPY(pr); - COPY(sr); COPY(pc); -#undef COPY - -#ifdef CONFIG_SH_FPU - if (current_cpu_data.flags & CPU_HAS_FPU) { - int owned_fp; - struct task_struct *tsk = current; - - regs->sr |= SR_FD; /* Release FPU */ - clear_fpu(tsk, regs); - clear_used_math(); - __get_user (owned_fp, &sc->sc_ownedfp); - if (owned_fp) - err |= restore_sigcontext_fpu(sc); - } -#endif - - regs->tra = -1; /* disable syscall checks */ - err |= __get_user(*r0_p, &sc->sc_regs[0]); - return err; -} - -asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15]; - sigset_t set; - int r0; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __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); - - if (restore_sigcontext(regs, &frame->sc, &r0)) - goto badframe; - return r0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; - sigset_t set; - stack_t st; - int r0; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - 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); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) - goto badframe; - - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame); - - return r0; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err = 0; - -#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) - COPY(regs[0]); COPY(regs[1]); - COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); - COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); - COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); - COPY(regs[14]); COPY(regs[15]); - COPY(gbr); COPY(mach); - COPY(macl); COPY(pr); - COPY(sr); COPY(pc); -#undef COPY - -#ifdef CONFIG_SH_FPU - err |= save_sigcontext_fpu(sc, regs); -#endif - - /* non-iBCS2 extensions.. */ - err |= __put_user(mask, &sc->oldmask); - - return err; -} - -/* - * Determine which stack to use.. - */ -static inline void __user * -get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) -{ - if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(sp) == 0) - sp = current->sas_ss_sp + current->sas_ss_size; - } - - return (void __user *)((sp - frame_size) & -8ul); -} - -/* These symbols are defined with the addresses in the vsyscall page. - See vsyscall-trapa.S. */ -extern void __user __kernel_sigreturn; -extern void __user __kernel_rt_sigreturn; - -static int setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - - if (_NSIG_WORDS > 1) - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - regs->pr = (unsigned long) ka->sa.sa_restorer; -#ifdef CONFIG_VSYSCALL - } else if (likely(current->mm->context.vdso)) { - regs->pr = VDSO_SYM(&__kernel_sigreturn); -#endif - } else { - /* Generate return code (system call to sigreturn) */ - err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP_NOARG, &frame->retcode[1]); - err |= __put_user(OR_R0_R0, &frame->retcode[2]); - err |= __put_user(OR_R0_R0, &frame->retcode[3]); - err |= __put_user(OR_R0_R0, &frame->retcode[4]); - err |= __put_user(OR_R0_R0, &frame->retcode[5]); - err |= __put_user(OR_R0_R0, &frame->retcode[6]); - err |= __put_user((__NR_sigreturn), &frame->retcode[7]); - regs->pr = (unsigned long) frame->retcode; - } - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - regs->regs[15] = (unsigned long) frame; - regs->regs[4] = signal; /* Arg for signal handler */ - regs->regs[5] = 0; - regs->regs[6] = (unsigned long) &frame->sc; - regs->pc = (unsigned long) ka->sa.sa_handler; - - set_fs(USER_DS); - - pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", - current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); - - flush_cache_sigtramp(regs->pr); - - if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) - flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); - - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; -} - -static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= copy_siginfo_to_user(&frame->info, info); - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, - &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[15]), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - regs->pr = (unsigned long) ka->sa.sa_restorer; -#ifdef CONFIG_VSYSCALL - } else if (likely(current->mm->context.vdso)) { - regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); -#endif - } else { - /* Generate return code (system call to rt_sigreturn) */ - err |= __put_user(MOVW(7), &frame->retcode[0]); - err |= __put_user(TRAP_NOARG, &frame->retcode[1]); - err |= __put_user(OR_R0_R0, &frame->retcode[2]); - err |= __put_user(OR_R0_R0, &frame->retcode[3]); - err |= __put_user(OR_R0_R0, &frame->retcode[4]); - err |= __put_user(OR_R0_R0, &frame->retcode[5]); - err |= __put_user(OR_R0_R0, &frame->retcode[6]); - err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]); - regs->pr = (unsigned long) frame->retcode; - } - - if (err) - goto give_sigsegv; - - /* Set up registers for signal handler */ - regs->regs[15] = (unsigned long) frame; - regs->regs[4] = signal; /* Arg for signal handler */ - regs->regs[5] = (unsigned long) &frame->info; - regs->regs[6] = (unsigned long) &frame->uc; - regs->pc = (unsigned long) ka->sa.sa_handler; - - set_fs(USER_DS); - - pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", - current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); - - flush_cache_sigtramp(regs->pr); - - if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) - flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); - - return 0; - -give_sigsegv: - force_sigsegv(sig, current); - return -EFAULT; -} - -/* - * OK, we're invoking a handler - */ - -static int -handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) -{ - int ret; - - /* Are we from a system call? */ - if (regs->tra >= 0) { - /* If so, check system call restarting.. */ - switch (regs->regs[0]) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - regs->regs[0] = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[0] = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - regs->regs[0] = save_r0; - regs->pc -= instruction_size( - ctrl_inw(regs->pc - 4)); - break; - } -#ifdef CONFIG_GUSA - } else { - /* gUSA handling */ - preempt_disable(); - - if (regs->regs[15] >= 0xc0000000) { - int offset = (int)regs->regs[15]; - - /* Reset stack pointer: clear critical region mark */ - regs->regs[15] = regs->regs[1]; - if (regs->pc < regs->regs[0]) - /* Go to rewind point #1 */ - regs->pc = regs->regs[0] + offset - - instruction_size(ctrl_inw(regs->pc-4)); - } - - preempt_enable_no_resched(); -#endif - } - - /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - ret = setup_rt_frame(sig, ka, info, oldset, regs); - else - ret = setup_frame(sig, ka, oldset, regs); - - if (ka->sa.sa_flags & SA_ONESHOT) - ka->sa.sa_handler = SIG_DFL; - - 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; -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -static void do_signal(struct pt_regs *regs, unsigned int save_r0) -{ - siginfo_t info; - int signr; - struct k_sigaction ka; - sigset_t *oldset; - - /* - * 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(regs)) - 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, regs, NULL); - if (signr > 0) { - /* Whee! Actually deliver the signal. */ - if (handle_signal(signr, &ka, &info, oldset, - regs, save_r0) == 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); - } - - return; - } - - no_signal: - /* Did we come from a system call? */ - if (regs->tra >= 0) { - /* Restart the system call - no handlers present */ - if (regs->regs[0] == -ERESTARTNOHAND || - regs->regs[0] == -ERESTARTSYS || - regs->regs[0] == -ERESTARTNOINTR) { - regs->regs[0] = save_r0; - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); - } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { - regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); - regs->regs[3] = __NR_restart_syscall; - } - } - - /* 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); - } -} - -asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, - __u32 thread_info_flags) -{ - /* deal with pending signal delivery */ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) - do_signal(regs, save_r0); -} diff -puN /dev/null arch/sh/kernel/signal_32.c --- /dev/null +++ a/arch/sh/kernel/signal_32.c @@ -0,0 +1,611 @@ +/* + * linux/arch/sh/kernel/signal.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + * + * 1997-11-28 Modified for POSIX.1b signals by Richard Henderson + * + * SuperH version: Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ +asmlinkage int +sys_sigsuspend(old_sigset_t mask, + unsigned long r5, unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + 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, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + + return do_sigaltstack(uss, uoss, regs->regs[15]); +} + + +/* + * Do a signal return; undo the signal stack. + */ + +#define MOVW(n) (0x9300|((n)-2)) /* Move mem word at PC+n to R3 */ +#if defined(CONFIG_CPU_SH2) +#define TRAP_NOARG 0xc320 /* Syscall w/no args (NR in R3) */ +#else +#define TRAP_NOARG 0xc310 /* Syscall w/no args (NR in R3) */ +#endif +#define OR_R0_R0 0x200b /* or r0,r0 (insert to avoid hardware bug) */ + +struct sigframe +{ + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + u16 retcode[8]; +}; + +struct rt_sigframe +{ + struct siginfo info; + struct ucontext uc; + u16 retcode[8]; +}; + +#ifdef CONFIG_SH_FPU +static inline int restore_sigcontext_fpu(struct sigcontext __user *sc) +{ + struct task_struct *tsk = current; + + if (!(current_cpu_data.flags & CPU_HAS_FPU)) + return 0; + + set_used_math(); + return __copy_from_user(&tsk->thread.fpu.hard, &sc->sc_fpregs[0], + sizeof(long)*(16*2+2)); +} + +static inline int save_sigcontext_fpu(struct sigcontext __user *sc, + struct pt_regs *regs) +{ + struct task_struct *tsk = current; + + if (!(current_cpu_data.flags & CPU_HAS_FPU)) + return 0; + + if (!used_math()) { + __put_user(0, &sc->sc_ownedfp); + return 0; + } + + __put_user(1, &sc->sc_ownedfp); + + /* This will cause a "finit" to be triggered by the next + attempted FPU operation by the 'current' process. + */ + clear_used_math(); + + unlazy_fpu(tsk, regs); + return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, + sizeof(long)*(16*2+2)); +} +#endif /* CONFIG_SH_FPU */ + +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *r0_p) +{ + unsigned int err = 0; + +#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) + COPY(regs[1]); + COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); + COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); + COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); + COPY(regs[14]); COPY(regs[15]); + COPY(gbr); COPY(mach); + COPY(macl); COPY(pr); + COPY(sr); COPY(pc); +#undef COPY + +#ifdef CONFIG_SH_FPU + if (current_cpu_data.flags & CPU_HAS_FPU) { + int owned_fp; + struct task_struct *tsk = current; + + regs->sr |= SR_FD; /* Release FPU */ + clear_fpu(tsk, regs); + clear_used_math(); + __get_user (owned_fp, &sc->sc_ownedfp); + if (owned_fp) + err |= restore_sigcontext_fpu(sc); + } +#endif + + regs->tra = -1; /* disable syscall checks */ + err |= __get_user(*r0_p, &sc->sc_regs[0]); + return err; +} + +asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct sigframe __user *frame = (struct sigframe __user *)regs->regs[15]; + sigset_t set; + int r0; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __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); + + if (restore_sigcontext(regs, &frame->sc, &r0)) + goto badframe; + return r0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + struct rt_sigframe __user *frame = (struct rt_sigframe __user *)regs->regs[15]; + sigset_t set; + stack_t st; + int r0; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + 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); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0)) + goto badframe; + + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack((const stack_t __user *)&st, NULL, (unsigned long)frame); + + return r0; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +static int +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, + unsigned long mask) +{ + int err = 0; + +#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) + COPY(regs[0]); COPY(regs[1]); + COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); + COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); + COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); + COPY(regs[14]); COPY(regs[15]); + COPY(gbr); COPY(mach); + COPY(macl); COPY(pr); + COPY(sr); COPY(pc); +#undef COPY + +#ifdef CONFIG_SH_FPU + err |= save_sigcontext_fpu(sc, regs); +#endif + + /* non-iBCS2 extensions.. */ + err |= __put_user(mask, &sc->oldmask); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void __user * +get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) +{ + if (ka->sa.sa_flags & SA_ONSTACK) { + if (sas_ss_flags(sp) == 0) + sp = current->sas_ss_sp + current->sas_ss_size; + } + + return (void __user *)((sp - frame_size) & -8ul); +} + +/* These symbols are defined with the addresses in the vsyscall page. + See vsyscall-trapa.S. */ +extern void __user __kernel_sigreturn; +extern void __user __kernel_rt_sigreturn; + +static int setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe __user *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); + + if (_NSIG_WORDS > 1) + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->pr = (unsigned long) ka->sa.sa_restorer; +#ifdef CONFIG_VSYSCALL + } else if (likely(current->mm->context.vdso)) { + regs->pr = VDSO_SYM(&__kernel_sigreturn); +#endif + } else { + /* Generate return code (system call to sigreturn) */ + err |= __put_user(MOVW(7), &frame->retcode[0]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); + err |= __put_user(OR_R0_R0, &frame->retcode[2]); + err |= __put_user(OR_R0_R0, &frame->retcode[3]); + err |= __put_user(OR_R0_R0, &frame->retcode[4]); + err |= __put_user(OR_R0_R0, &frame->retcode[5]); + err |= __put_user(OR_R0_R0, &frame->retcode[6]); + err |= __put_user((__NR_sigreturn), &frame->retcode[7]); + regs->pr = (unsigned long) frame->retcode; + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->regs[15] = (unsigned long) frame; + regs->regs[4] = signal; /* Arg for signal handler */ + regs->regs[5] = 0; + regs->regs[6] = (unsigned long) &frame->sc; + regs->pc = (unsigned long) ka->sa.sa_handler; + + set_fs(USER_DS); + + pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", + current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); + + flush_cache_sigtramp(regs->pr); + + if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) + flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); + + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return -EFAULT; +} + +static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe __user *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs->regs[15], sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= copy_siginfo_to_user(&frame->info, info); + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->regs[15]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + regs->pr = (unsigned long) ka->sa.sa_restorer; +#ifdef CONFIG_VSYSCALL + } else if (likely(current->mm->context.vdso)) { + regs->pr = VDSO_SYM(&__kernel_rt_sigreturn); +#endif + } else { + /* Generate return code (system call to rt_sigreturn) */ + err |= __put_user(MOVW(7), &frame->retcode[0]); + err |= __put_user(TRAP_NOARG, &frame->retcode[1]); + err |= __put_user(OR_R0_R0, &frame->retcode[2]); + err |= __put_user(OR_R0_R0, &frame->retcode[3]); + err |= __put_user(OR_R0_R0, &frame->retcode[4]); + err |= __put_user(OR_R0_R0, &frame->retcode[5]); + err |= __put_user(OR_R0_R0, &frame->retcode[6]); + err |= __put_user((__NR_rt_sigreturn), &frame->retcode[7]); + regs->pr = (unsigned long) frame->retcode; + } + + if (err) + goto give_sigsegv; + + /* Set up registers for signal handler */ + regs->regs[15] = (unsigned long) frame; + regs->regs[4] = signal; /* Arg for signal handler */ + regs->regs[5] = (unsigned long) &frame->info; + regs->regs[6] = (unsigned long) &frame->uc; + regs->pc = (unsigned long) ka->sa.sa_handler; + + set_fs(USER_DS); + + pr_debug("SIG deliver (%s:%d): sp=%p pc=%08lx pr=%08lx\n", + current->comm, task_pid_nr(current), frame, regs->pc, regs->pr); + + flush_cache_sigtramp(regs->pr); + + if ((-regs->pr & (L1_CACHE_BYTES-1)) < sizeof(frame->retcode)) + flush_cache_sigtramp(regs->pr + L1_CACHE_BYTES); + + return 0; + +give_sigsegv: + force_sigsegv(sig, current); + return -EFAULT; +} + +/* + * OK, we're invoking a handler + */ + +static int +handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0) +{ + int ret; + + /* Are we from a system call? */ + if (regs->tra >= 0) { + /* If so, check system call restarting.. */ + switch (regs->regs[0]) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + regs->regs[0] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[0] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + regs->regs[0] = save_r0; + regs->pc -= instruction_size( + ctrl_inw(regs->pc - 4)); + break; + } + } + + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + ret = setup_rt_frame(sig, ka, info, oldset, regs); + else + ret = setup_frame(sig, ka, oldset, regs); + + if (ka->sa.sa_flags & SA_ONESHOT) + ka->sa.sa_handler = SIG_DFL; + + 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; +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +static void do_signal(struct pt_regs *regs, unsigned int save_r0) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; + sigset_t *oldset; + + /* + * 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(regs)) + 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, regs, NULL); + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + if (handle_signal(signr, &ka, &info, oldset, + regs, save_r0) == 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); + } + + return; + } + + no_signal: + /* Did we come from a system call? */ + if (regs->tra >= 0) { + /* Restart the system call - no handlers present */ + if (regs->regs[0] == -ERESTARTNOHAND || + regs->regs[0] == -ERESTARTSYS || + regs->regs[0] == -ERESTARTNOINTR) { + regs->regs[0] = save_r0; + regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + } else if (regs->regs[0] == -ERESTART_RESTARTBLOCK) { + regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); + regs->regs[3] = __NR_restart_syscall; + } + } + + /* 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); + } +} + +asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, + __u32 thread_info_flags) +{ + /* deal with pending signal delivery */ + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + do_signal(regs, save_r0); +} diff -puN /dev/null arch/sh/kernel/signal_64.c --- /dev/null +++ a/arch/sh/kernel/signal_64.c @@ -0,0 +1,751 @@ +/* + * arch/sh/kernel/signal_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define REG_RET 9 +#define REG_ARG1 2 +#define REG_ARG2 3 +#define REG_ARG3 4 +#define REG_SP 15 +#define REG_PR 18 +#define REF_REG_RET regs->regs[REG_RET] +#define REF_REG_SP regs->regs[REG_SP] +#define DEREF_REG_PR regs->regs[REG_PR] + +#define DEBUG_SIG 0 + +#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) + +asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); + +/* + * Atomically swap in the new signal mask, and wait for a signal. + */ + +asmlinkage int +sys_sigsuspend(old_sigset_t mask, + unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs * regs) +{ + sigset_t saveset; + + mask &= _BLOCKABLE; + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + siginitset(¤t->blocked, mask); + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + REF_REG_RET = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + regs->pc += 4; /* because sys_sigreturn decrements the pc */ + if (do_signal(regs, &saveset)) { + /* pc now points at signal handler. Need to decrement + it because entry.S will increment it. */ + regs->pc -= 4; + return -EINTR; + } + } +} + +asmlinkage int +sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, + unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, + struct pt_regs * regs) +{ + sigset_t saveset, newset; + + /* XXX: Don't preclude handling different sized sigset_t's. */ + if (sigsetsize != sizeof(sigset_t)) + return -EINVAL; + + if (copy_from_user(&newset, unewset, sizeof(newset))) + return -EFAULT; + sigdelsetmask(&newset, ~_BLOCKABLE); + spin_lock_irq(¤t->sighand->siglock); + saveset = current->blocked; + current->blocked = newset; + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); + + REF_REG_RET = -EINTR; + while (1) { + current->state = TASK_INTERRUPTIBLE; + schedule(); + regs->pc += 4; /* because sys_sigreturn decrements the pc */ + if (do_signal(regs, &saveset)) { + /* pc now points at signal handler. Need to decrement + it because entry.S will increment it. */ + regs->pc -= 4; + return -EINTR; + } + } +} + +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, + unsigned long r4, unsigned long r5, unsigned long r6, + unsigned long r7, + struct pt_regs * regs) +{ + return do_sigaltstack(uss, uoss, REF_REG_SP); +} + + +/* + * Do a signal return; undo the signal stack. + */ + +struct sigframe +{ + struct sigcontext sc; + unsigned long extramask[_NSIG_WORDS-1]; + long long retcode[2]; +}; + +struct rt_sigframe +{ + struct siginfo __user *pinfo; + void *puc; + struct siginfo info; + struct ucontext uc; + long long retcode[2]; +}; + +#ifdef CONFIG_SH_FPU +static inline int +restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) +{ + int err = 0; + int fpvalid; + + err |= __get_user (fpvalid, &sc->sc_fpvalid); + conditional_used_math(fpvalid); + if (! fpvalid) + return err; + + if (current == last_task_used_math) { + last_task_used_math = NULL; + regs->sr |= SR_FD; + } + + err |= __copy_from_user(¤t->thread.fpu.hard, &sc->sc_fpregs[0], + (sizeof(long long) * 32) + (sizeof(int) * 1)); + + return err; +} + +static inline int +setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) +{ + int err = 0; + int fpvalid; + + fpvalid = !!used_math(); + err |= __put_user(fpvalid, &sc->sc_fpvalid); + if (! fpvalid) + return err; + + if (current == last_task_used_math) { + enable_fpu(); + save_fpu(current, regs); + disable_fpu(); + last_task_used_math = NULL; + regs->sr |= SR_FD; + } + + err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.fpu.hard, + (sizeof(long long) * 32) + (sizeof(int) * 1)); + clear_used_math(); + + return err; +} +#else +static inline int +restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) +{ + return 0; +} +static inline int +setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) +{ + return 0; +} +#endif + +static int +restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p) +{ + unsigned int err = 0; + unsigned long long current_sr, new_sr; +#define SR_MASK 0xffff8cfd + +#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) + + COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); + COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); + COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); + COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); + COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); + COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); + COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); + COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); + COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); + COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); + COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); + COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); + COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); + COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); + COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); + + /* Prevent the signal handler manipulating SR in a way that can + crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be + modified */ + current_sr = regs->sr; + err |= __get_user(new_sr, &sc->sc_sr); + regs->sr &= SR_MASK; + regs->sr |= (new_sr & ~SR_MASK); + + COPY(pc); + +#undef COPY + + /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr + * has been restored above.) */ + err |= restore_sigcontext_fpu(regs, sc); + + regs->syscall_nr = -1; /* disable syscall checks */ + err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]); + return err; +} + +asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3, + unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs * regs) +{ + struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP; + sigset_t set; + long long ret; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + if (__get_user(set.sig[0], &frame->sc.oldmask) + || (_NSIG_WORDS > 1 + && __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); + + if (restore_sigcontext(regs, &frame->sc, &ret)) + goto badframe; + regs->pc -= 4; + + return (int) ret; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, + unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs * regs) +{ + struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP; + sigset_t set; + stack_t __user st; + long long ret; + + if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) + goto badframe; + + 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); + + if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) + goto badframe; + regs->pc -= 4; + + if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) + goto badframe; + /* It is more difficult to avoid calling this function than to + call it and ignore errors. */ + do_sigaltstack(&st, NULL, REF_REG_SP); + + return (int) ret; + +badframe: + force_sig(SIGSEGV, current); + return 0; +} + +/* + * Set up a signal frame. + */ + +static int +setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, + unsigned long mask) +{ + int err = 0; + + /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */ + err |= setup_sigcontext_fpu(regs, sc); + +#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) + + COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); + COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); + COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); + COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); + COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); + COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); + COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); + COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); + COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); + COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); + COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); + COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); + COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); + COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); + COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); + COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); + COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); + COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); + COPY(sr); COPY(pc); + +#undef COPY + + err |= __put_user(mask, &sc->oldmask); + + return err; +} + +/* + * Determine which stack to use.. + */ +static inline void __user * +get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) +{ + if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) + sp = current->sas_ss_sp + current->sas_ss_size; + + return (void __user *)((sp - frame_size) & -8ul); +} + +void sa_default_restorer(void); /* See comments below */ +void sa_default_rt_restorer(void); /* See comments below */ + +static void setup_frame(int sig, struct k_sigaction *ka, + sigset_t *set, struct pt_regs *regs) +{ + struct sigframe __user *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); + + /* Give up earlier as i386, in case */ + if (err) + goto give_sigsegv; + + if (_NSIG_WORDS > 1) { + err |= __copy_to_user(frame->extramask, &set->sig[1], + sizeof(frame->extramask)); } + + /* Give up earlier as i386, in case */ + if (err) + goto give_sigsegv; + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; + + /* + * On SH5 all edited pointers are subject to NEFF + */ + DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? + (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + } else { + /* + * Different approach on SH5. + * . Endianness independent asm code gets placed in entry.S . + * This is limited to four ASM instructions corresponding + * to two long longs in size. + * . err checking is done on the else branch only + * . flush_icache_range() is called upon __put_user() only + * . all edited pointers are subject to NEFF + * . being code, linker turns ShMedia bit on, always + * dereference index -1. + */ + DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; + DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? + (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + + if (__copy_to_user(frame->retcode, + (unsigned long long)sa_default_restorer & (~1), 16) != 0) + goto give_sigsegv; + + /* Cohere the trampoline with the I-cache. */ + flush_cache_sigtramp(DEREF_REG_PR-1); + } + + /* + * Set up registers for signal handler. + * All edited pointers are subject to NEFF. + */ + regs->regs[REG_SP] = (unsigned long) frame; + regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? + (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; + regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ + + /* FIXME: + The glibc profiling support for SH-5 needs to be passed a sigcontext + so it can retrieve the PC. At some point during 2003 the glibc + support was changed to receive the sigcontext through the 2nd + argument, but there are still versions of libc.so in use that use + the 3rd argument. Until libc.so is stabilised, pass the sigcontext + through both 2nd and 3rd arguments. + */ + + regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; + regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; + + regs->pc = (unsigned long) ka->sa.sa_handler; + regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; + + set_fs(USER_DS); + +#if DEBUG_SIG + /* Broken %016Lx */ + printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", + signal, + current->comm, current->pid, frame, + regs->pc >> 32, regs->pc & 0xffffffff, + DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); +#endif + + return; + +give_sigsegv: + force_sigsegv(sig, current); +} + +static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, + sigset_t *set, struct pt_regs *regs) +{ + struct rt_sigframe __user *frame; + int err = 0; + int signal; + + frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); + + if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) + goto give_sigsegv; + + signal = current_thread_info()->exec_domain + && current_thread_info()->exec_domain->signal_invmap + && sig < 32 + ? current_thread_info()->exec_domain->signal_invmap[sig] + : sig; + + err |= __put_user(&frame->info, &frame->pinfo); + err |= __put_user(&frame->uc, &frame->puc); + err |= copy_siginfo_to_user(&frame->info, info); + + /* Give up earlier as i386, in case */ + if (err) + goto give_sigsegv; + + /* Create the ucontext. */ + err |= __put_user(0, &frame->uc.uc_flags); + err |= __put_user(0, &frame->uc.uc_link); + err |= __put_user((void *)current->sas_ss_sp, + &frame->uc.uc_stack.ss_sp); + err |= __put_user(sas_ss_flags(regs->regs[REG_SP]), + &frame->uc.uc_stack.ss_flags); + err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); + err |= setup_sigcontext(&frame->uc.uc_mcontext, + regs, set->sig[0]); + err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); + + /* Give up earlier as i386, in case */ + if (err) + goto give_sigsegv; + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + if (ka->sa.sa_flags & SA_RESTORER) { + DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; + + /* + * On SH5 all edited pointers are subject to NEFF + */ + DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? + (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + } else { + /* + * Different approach on SH5. + * . Endianness independent asm code gets placed in entry.S . + * This is limited to four ASM instructions corresponding + * to two long longs in size. + * . err checking is done on the else branch only + * . flush_icache_range() is called upon __put_user() only + * . all edited pointers are subject to NEFF + * . being code, linker turns ShMedia bit on, always + * dereference index -1. + */ + + DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; + DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? + (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; + + if (__copy_to_user(frame->retcode, + (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0) + goto give_sigsegv; + + flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); + } + + /* + * Set up registers for signal handler. + * All edited pointers are subject to NEFF. + */ + regs->regs[REG_SP] = (unsigned long) frame; + regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? + (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; + regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ + regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; + regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; + regs->pc = (unsigned long) ka->sa.sa_handler; + regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; + + set_fs(USER_DS); + +#if DEBUG_SIG + /* Broken %016Lx */ + printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", + signal, + current->comm, current->pid, frame, + regs->pc >> 32, regs->pc & 0xffffffff, + DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); +#endif + + return; + +give_sigsegv: + force_sigsegv(sig, current); +} + +/* + * OK, we're invoking a handler + */ + +static void +handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, + sigset_t *oldset, struct pt_regs * regs) +{ + /* Are we from a system call? */ + if (regs->syscall_nr >= 0) { + /* If so, check system call restarting.. */ + switch (regs->regs[REG_RET]) { + case -ERESTART_RESTARTBLOCK: + case -ERESTARTNOHAND: + regs->regs[REG_RET] = -EINTR; + break; + + case -ERESTARTSYS: + if (!(ka->sa.sa_flags & SA_RESTART)) { + regs->regs[REG_RET] = -EINTR; + break; + } + /* fallthrough */ + case -ERESTARTNOINTR: + /* Decode syscall # */ + regs->regs[REG_RET] = regs->syscall_nr; + regs->pc -= 4; + } + } + + /* Set up the stack frame */ + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame(sig, ka, info, oldset, regs); + else + setup_frame(sig, ka, oldset, regs); + + 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); +} + +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +int do_signal(struct pt_regs *regs, sigset_t *oldset) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; + + /* + * 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(regs)) + return 1; + + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, 0); + + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + handle_signal(signr, &info, &ka, oldset, regs); + + /* + * If a signal was successfully delivered, the saved sigmask + * is in its frame, and we can clear the TIF_RESTORE_SIGMASK + * flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + return 1; + } + +no_signal: + /* Did we come from a system call? */ + if (regs->syscall_nr >= 0) { + /* Restart the system call - no handlers present */ + switch (regs->regs[REG_RET]) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + /* Decode Syscall # */ + regs->regs[REG_RET] = regs->syscall_nr; + regs->pc -= 4; + break; + + case -ERESTART_RESTARTBLOCK: + regs->regs[REG_RET] = __NR_restart_syscall; + regs->pc -= 4; + break; + } + } + + /* No signal to deliver -- 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); + } + + return 0; +} diff -puN arch/sh/kernel/sys_sh.c~git-sh arch/sh/kernel/sys_sh.c --- a/arch/sh/kernel/sys_sh.c~git-sh +++ a/arch/sh/kernel/sys_sh.c @@ -7,7 +7,6 @@ * * Taken from i386 version. */ - #include #include #include @@ -27,28 +26,7 @@ #include #include -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - int fd[2]; - int error; - - error = do_pipe(fd); - if (!error) { - regs->regs[1] = fd[1]; - return fd[0]; - } - return error; -} - unsigned long shm_align_mask = PAGE_SIZE - 1; /* Sane caches */ - EXPORT_SYMBOL(shm_align_mask); #ifdef CONFIG_MMU @@ -140,7 +118,7 @@ full_search: #endif /* CONFIG_MMU */ static inline long -do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, +do_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, int fd, unsigned long pgoff) { int error = -EBADF; @@ -195,12 +173,13 @@ asmlinkage int sys_ipc(uint call, int fi if (call <= SEMCTL) switch (call) { case SEMOP: - return sys_semtimedop(first, (struct sembuf __user *)ptr, + 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); + return sys_semtimedop(first, + (struct sembuf __user *)ptr, second, + (const struct timespec __user *)fifth); case SEMGET: return sys_semget (first, second, third); case SEMCTL: { @@ -215,25 +194,28 @@ asmlinkage int sys_ipc(uint call, int fi return -EINVAL; } - if (call <= MSGCTL) + if (call <= MSGCTL) switch (call) { case MSGSND: - return sys_msgsnd (first, (struct msgbuf __user *) ptr, + return sys_msgsnd (first, (struct msgbuf __user *) ptr, second, third); case MSGRCV: switch (version) { - case 0: { + case 0: + { struct ipc_kludge tmp; + if (!ptr) return -EINVAL; - + if (copy_from_user(&tmp, - (struct ipc_kludge __user *) ptr, + (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, @@ -247,7 +229,7 @@ asmlinkage int sys_ipc(uint call, int fi default: return -EINVAL; } - if (call <= SHMCTL) + if (call <= SHMCTL) switch (call) { case SHMAT: switch (version) { @@ -265,7 +247,7 @@ asmlinkage int sys_ipc(uint call, int fi return do_shmat (first, (char __user *) ptr, second, (ulong *) third); } - case SHMDT: + case SHMDT: return sys_shmdt ((char __user *)ptr); case SHMGET: return sys_shmget (first, second, third); @@ -275,7 +257,7 @@ asmlinkage int sys_ipc(uint call, int fi default: return -EINVAL; } - + return -EINVAL; } @@ -289,49 +271,3 @@ asmlinkage int sys_uname(struct old_utsn up_read(&uts_sem); return err?-EFAULT:0; } - -asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf, - size_t count, long dummy, loff_t pos) -{ - return sys_pread64(fd, buf, count, pos); -} - -asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf, - size_t count, long dummy, loff_t pos) -{ - return sys_pwrite64(fd, buf, count, pos); -} - -asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, - u32 len0, u32 len1, int advice) -{ -#ifdef __LITTLE_ENDIAN__ - return sys_fadvise64_64(fd, (u64)offset1 << 32 | offset0, - (u64)len1 << 32 | len0, advice); -#else - return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1, - (u64)len0 << 32 | len1, advice); -#endif -} - -#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) -#define SYSCALL_ARG3 "trapa #0x23" -#else -#define SYSCALL_ARG3 "trapa #0x13" -#endif - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register long __sc0 __asm__ ("r3") = __NR_execve; - register long __sc4 __asm__ ("r4") = (long) filename; - register long __sc5 __asm__ ("r5") = (long) argv; - register long __sc6 __asm__ ("r6") = (long) envp; - __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) - : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) - : "memory"); - return __sc0; -} diff -puN /dev/null arch/sh/kernel/sys_sh32.c --- /dev/null +++ a/arch/sh/kernel/sys_sh32.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way Unix traditionally does this, though. + */ +asmlinkage int sys_pipe(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + int fd[2]; + int error; + + error = do_pipe(fd); + if (!error) { + regs->regs[1] = fd[1]; + return fd[0]; + } + return error; +} + +asmlinkage ssize_t sys_pread_wrapper(unsigned int fd, char * buf, + size_t count, long dummy, loff_t pos) +{ + return sys_pread64(fd, buf, count, pos); +} + +asmlinkage ssize_t sys_pwrite_wrapper(unsigned int fd, const char * buf, + size_t count, long dummy, loff_t pos) +{ + return sys_pwrite64(fd, buf, count, pos); +} + +asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, + u32 len0, u32 len1, int advice) +{ +#ifdef __LITTLE_ENDIAN__ + return sys_fadvise64_64(fd, (u64)offset1 << 32 | offset0, + (u64)len1 << 32 | len0, advice); +#else + return sys_fadvise64_64(fd, (u64)offset0 << 32 | offset1, + (u64)len0 << 32 | len1, advice); +#endif +} + +#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A) +#define SYSCALL_ARG3 "trapa #0x23" +#else +#define SYSCALL_ARG3 "trapa #0x13" +#endif + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register long __sc0 __asm__ ("r3") = __NR_execve; + register long __sc4 __asm__ ("r4") = (long) filename; + register long __sc5 __asm__ ("r5") = (long) argv; + register long __sc6 __asm__ ("r6") = (long) envp; + __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0) + : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6) + : "memory"); + return __sc0; +} diff -puN /dev/null arch/sh/kernel/sys_sh64.c --- /dev/null +++ a/arch/sh/kernel/sys_sh64.c @@ -0,0 +1,66 @@ +/* + * arch/sh/kernel/sys_sh64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * This file contains various random system calls that + * have a non-standard calling sequence on the Linux/SH5 + * platform. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way Unix traditionally does this, though. + */ +asmlinkage int 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; +} + +/* + * Do a system call from kernel instead of calling sys_execve so we + * end up with proper pt_regs. + */ +int kernel_execve(const char *filename, char *const argv[], char *const envp[]) +{ + register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); + register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; + register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; + register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; + __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" + : "=r" (__sc0) + : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); + __asm__ __volatile__ ("!dummy %0 %1 %2 %3" + : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); + return __sc0; +} diff -puN arch/sh/kernel/syscalls.S~git-sh /dev/null --- a/arch/sh/kernel/syscalls.S +++ /dev/null @@ -1,343 +0,0 @@ -/* - * arch/sh/kernel/syscalls.S - * - * System call table for SuperH - * - * Copyright (C) 1999, 2000, 2002 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ -#include -#include - - .data -ENTRY(sys_call_table) - .long sys_restart_syscall /* 0 - old "setup()" system call*/ - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sys_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys() */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_ni_syscall /* sys_olduname */ - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_ni_syscall /* sys_oldselect */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long old_readdir - .long old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* ioperm */ - .long sys_socketcall - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_uname - .long sys_ni_syscall /* 110 */ /* iopl */ - .long sys_vhangup - .long sys_ni_syscall /* idle */ - .long sys_ni_syscall /* vm86old */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc - .long sys_fsync - .long sys_sigreturn - .long sys_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .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 - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* vm86 */ - .long sys_ni_syscall /* old "query_module" */ - .long sys_poll - .long sys_nfsservctl - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread_wrapper /* 180 */ - .long sys_pwrite_wrapper - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long sys_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long sys_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap2 - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - .long sys_getdents64 /* 220 */ - .long sys_fcntl64 - .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall /* Reserved for Security */ - .long sys_gettid - .long sys_readahead /* 225 */ - .long sys_setxattr - .long sys_lsetxattr - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr /* 230 */ - .long sys_fgetxattr - .long sys_listxattr - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr /* 235 */ - .long sys_lremovexattr - .long sys_fremovexattr - .long sys_tkill - .long sys_sendfile64 - .long sys_futex /* 240 */ - .long sys_sched_setaffinity - .long sys_sched_getaffinity - .long sys_ni_syscall - .long sys_ni_syscall - .long sys_io_setup /* 245 */ - .long sys_io_destroy - .long sys_io_getevents - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 /* 250 */ - .long sys_ni_syscall - .long sys_exit_group - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl /* 255 */ - .long sys_epoll_wait - .long sys_remap_file_pages - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime /* 260 */ - .long sys_timer_gettime - .long sys_timer_getoverrun - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime /* 265 */ - .long sys_clock_getres - .long sys_clock_nanosleep - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill /* 270 */ - .long sys_utimes - .long sys_fadvise64_64_wrapper - .long sys_ni_syscall /* Reserved for vserver */ - .long sys_mbind - .long sys_get_mempolicy /* 275 */ - .long sys_set_mempolicy - .long sys_mq_open - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive /* 280 */ - .long sys_mq_notify - .long sys_mq_getsetattr - .long sys_kexec_load - .long sys_waitid - .long sys_add_key /* 285 */ - .long sys_request_key - .long sys_keyctl - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init /* 290 */ - .long sys_inotify_add_watch - .long sys_inotify_rm_watch - .long sys_ni_syscall - .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 - .long sys_eventfd - .long sys_fallocate diff -puN /dev/null arch/sh/kernel/syscalls_32.S --- /dev/null +++ a/arch/sh/kernel/syscalls_32.S @@ -0,0 +1,343 @@ +/* + * arch/sh/kernel/syscalls.S + * + * System call table for SuperH + * + * Copyright (C) 1999, 2000, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + */ +#include +#include + + .data +ENTRY(sys_call_table) + .long sys_restart_syscall /* 0 - old "setup()" system call*/ + .long sys_exit + .long sys_fork + .long sys_read + .long sys_write + .long sys_open /* 5 */ + .long sys_close + .long sys_waitpid + .long sys_creat + .long sys_link + .long sys_unlink /* 10 */ + .long sys_execve + .long sys_chdir + .long sys_time + .long sys_mknod + .long sys_chmod /* 15 */ + .long sys_lchown16 + .long sys_ni_syscall /* old break syscall holder */ + .long sys_stat + .long sys_lseek + .long sys_getpid /* 20 */ + .long sys_mount + .long sys_oldumount + .long sys_setuid16 + .long sys_getuid16 + .long sys_stime /* 25 */ + .long sys_ptrace + .long sys_alarm + .long sys_fstat + .long sys_pause + .long sys_utime /* 30 */ + .long sys_ni_syscall /* old stty syscall holder */ + .long sys_ni_syscall /* old gtty syscall holder */ + .long sys_access + .long sys_nice + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ + .long sys_sync + .long sys_kill + .long sys_rename + .long sys_mkdir + .long sys_rmdir /* 40 */ + .long sys_dup + .long sys_pipe + .long sys_times + .long sys_ni_syscall /* old prof syscall holder */ + .long sys_brk /* 45 */ + .long sys_setgid16 + .long sys_getgid16 + .long sys_signal + .long sys_geteuid16 + .long sys_getegid16 /* 50 */ + .long sys_acct + .long sys_umount /* recycled never used phys() */ + .long sys_ni_syscall /* old lock syscall holder */ + .long sys_ioctl + .long sys_fcntl /* 55 */ + .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_setpgid + .long sys_ni_syscall /* old ulimit syscall holder */ + .long sys_ni_syscall /* sys_olduname */ + .long sys_umask /* 60 */ + .long sys_chroot + .long sys_ustat + .long sys_dup2 + .long sys_getppid + .long sys_getpgrp /* 65 */ + .long sys_setsid + .long sys_sigaction + .long sys_sgetmask + .long sys_ssetmask + .long sys_setreuid16 /* 70 */ + .long sys_setregid16 + .long sys_sigsuspend + .long sys_sigpending + .long sys_sethostname + .long sys_setrlimit /* 75 */ + .long sys_old_getrlimit + .long sys_getrusage + .long sys_gettimeofday + .long sys_settimeofday + .long sys_getgroups16 /* 80 */ + .long sys_setgroups16 + .long sys_ni_syscall /* sys_oldselect */ + .long sys_symlink + .long sys_lstat + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_swapon + .long sys_reboot + .long old_readdir + .long old_mmap /* 90 */ + .long sys_munmap + .long sys_truncate + .long sys_ftruncate + .long sys_fchmod + .long sys_fchown16 /* 95 */ + .long sys_getpriority + .long sys_setpriority + .long sys_ni_syscall /* old profil syscall holder */ + .long sys_statfs + .long sys_fstatfs /* 100 */ + .long sys_ni_syscall /* ioperm */ + .long sys_socketcall + .long sys_syslog + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_uname + .long sys_ni_syscall /* 110 */ /* iopl */ + .long sys_vhangup + .long sys_ni_syscall /* idle */ + .long sys_ni_syscall /* vm86old */ + .long sys_wait4 + .long sys_swapoff /* 115 */ + .long sys_sysinfo + .long sys_ipc + .long sys_fsync + .long sys_sigreturn + .long sys_clone /* 120 */ + .long sys_setdomainname + .long sys_newuname + .long sys_ni_syscall /* sys_modify_ldt */ + .long sys_adjtimex + .long sys_mprotect /* 125 */ + .long sys_sigprocmask + .long sys_ni_syscall /* old "create_module" */ + .long sys_init_module + .long sys_delete_module + .long sys_ni_syscall /* 130: old "get_kernel_syms" */ + .long sys_quotactl + .long sys_getpgid + .long sys_fchdir + .long sys_bdflush + .long sys_sysfs /* 135 */ + .long sys_personality + .long sys_ni_syscall /* for afs_syscall */ + .long sys_setfsuid16 + .long sys_setfsgid16 + .long sys_llseek /* 140 */ + .long sys_getdents + .long sys_select + .long sys_flock + .long sys_msync + .long sys_readv /* 145 */ + .long sys_writev + .long sys_getsid + .long sys_fdatasync + .long sys_sysctl + .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 + .long sys_sched_getscheduler + .long sys_sched_yield + .long sys_sched_get_priority_max + .long sys_sched_get_priority_min /* 160 */ + .long sys_sched_rr_get_interval + .long sys_nanosleep + .long sys_mremap + .long sys_setresuid16 + .long sys_getresuid16 /* 165 */ + .long sys_ni_syscall /* vm86 */ + .long sys_ni_syscall /* old "query_module" */ + .long sys_poll + .long sys_nfsservctl + .long sys_setresgid16 /* 170 */ + .long sys_getresgid16 + .long sys_prctl + .long sys_rt_sigreturn + .long sys_rt_sigaction + .long sys_rt_sigprocmask /* 175 */ + .long sys_rt_sigpending + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend + .long sys_pread_wrapper /* 180 */ + .long sys_pwrite_wrapper + .long sys_chown16 + .long sys_getcwd + .long sys_capget + .long sys_capset /* 185 */ + .long sys_sigaltstack + .long sys_sendfile + .long sys_ni_syscall /* streams1 */ + .long sys_ni_syscall /* streams2 */ + .long sys_vfork /* 190 */ + .long sys_getrlimit + .long sys_mmap2 + .long sys_truncate64 + .long sys_ftruncate64 + .long sys_stat64 /* 195 */ + .long sys_lstat64 + .long sys_fstat64 + .long sys_lchown + .long sys_getuid + .long sys_getgid /* 200 */ + .long sys_geteuid + .long sys_getegid + .long sys_setreuid + .long sys_setregid + .long sys_getgroups /* 205 */ + .long sys_setgroups + .long sys_fchown + .long sys_setresuid + .long sys_getresuid + .long sys_setresgid /* 210 */ + .long sys_getresgid + .long sys_chown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_mincore + .long sys_madvise + .long sys_getdents64 /* 220 */ + .long sys_fcntl64 + .long sys_ni_syscall /* reserved for TUX */ + .long sys_ni_syscall /* Reserved for Security */ + .long sys_gettid + .long sys_readahead /* 225 */ + .long sys_setxattr + .long sys_lsetxattr + .long sys_fsetxattr + .long sys_getxattr + .long sys_lgetxattr /* 230 */ + .long sys_fgetxattr + .long sys_listxattr + .long sys_llistxattr + .long sys_flistxattr + .long sys_removexattr /* 235 */ + .long sys_lremovexattr + .long sys_fremovexattr + .long sys_tkill + .long sys_sendfile64 + .long sys_futex /* 240 */ + .long sys_sched_setaffinity + .long sys_sched_getaffinity + .long sys_ni_syscall + .long sys_ni_syscall + .long sys_io_setup /* 245 */ + .long sys_io_destroy + .long sys_io_getevents + .long sys_io_submit + .long sys_io_cancel + .long sys_fadvise64 /* 250 */ + .long sys_ni_syscall + .long sys_exit_group + .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl /* 255 */ + .long sys_epoll_wait + .long sys_remap_file_pages + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime /* 260 */ + .long sys_timer_gettime + .long sys_timer_getoverrun + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime /* 265 */ + .long sys_clock_getres + .long sys_clock_nanosleep + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill /* 270 */ + .long sys_utimes + .long sys_fadvise64_64_wrapper + .long sys_ni_syscall /* Reserved for vserver */ + .long sys_mbind + .long sys_get_mempolicy /* 275 */ + .long sys_set_mempolicy + .long sys_mq_open + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive /* 280 */ + .long sys_mq_notify + .long sys_mq_getsetattr + .long sys_kexec_load + .long sys_waitid + .long sys_add_key /* 285 */ + .long sys_request_key + .long sys_keyctl + .long sys_ioprio_set + .long sys_ioprio_get + .long sys_inotify_init /* 290 */ + .long sys_inotify_add_watch + .long sys_inotify_rm_watch + .long sys_ni_syscall + .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 + .long sys_eventfd + .long sys_fallocate diff -puN /dev/null arch/sh/kernel/syscalls_64.S --- /dev/null +++ a/arch/sh/kernel/syscalls_64.S @@ -0,0 +1,381 @@ +/* + * arch/sh/kernel/syscalls_64.S + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2004 - 2007 Paul Mundt + * Copyright (C) 2003, 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include + + .section .data, "aw" + .balign 32 + +/* + * System calls jump table + */ + .globl sys_call_table +sys_call_table: + .long sys_restart_syscall /* 0 - old "setup()" system call */ + .long sys_exit + .long sys_fork + .long sys_read + .long sys_write + .long sys_open /* 5 */ + .long sys_close + .long sys_waitpid + .long sys_creat + .long sys_link + .long sys_unlink /* 10 */ + .long sys_execve + .long sys_chdir + .long sys_time + .long sys_mknod + .long sys_chmod /* 15 */ + .long sys_lchown16 + .long sys_ni_syscall /* old break syscall holder */ + .long sys_stat + .long sys_lseek + .long sys_getpid /* 20 */ + .long sys_mount + .long sys_oldumount + .long sys_setuid16 + .long sys_getuid16 + .long sys_stime /* 25 */ + .long sh64_ptrace + .long sys_alarm + .long sys_fstat + .long sys_pause + .long sys_utime /* 30 */ + .long sys_ni_syscall /* old stty syscall holder */ + .long sys_ni_syscall /* old gtty syscall holder */ + .long sys_access + .long sys_nice + .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ + .long sys_sync + .long sys_kill + .long sys_rename + .long sys_mkdir + .long sys_rmdir /* 40 */ + .long sys_dup + .long sys_pipe + .long sys_times + .long sys_ni_syscall /* old prof syscall holder */ + .long sys_brk /* 45 */ + .long sys_setgid16 + .long sys_getgid16 + .long sys_signal + .long sys_geteuid16 + .long sys_getegid16 /* 50 */ + .long sys_acct + .long sys_umount /* recycled never used phys( */ + .long sys_ni_syscall /* old lock syscall holder */ + .long sys_ioctl + .long sys_fcntl /* 55 */ + .long sys_ni_syscall /* old mpx syscall holder */ + .long sys_setpgid + .long sys_ni_syscall /* old ulimit syscall holder */ + .long sys_ni_syscall /* sys_olduname */ + .long sys_umask /* 60 */ + .long sys_chroot + .long sys_ustat + .long sys_dup2 + .long sys_getppid + .long sys_getpgrp /* 65 */ + .long sys_setsid + .long sys_sigaction + .long sys_sgetmask + .long sys_ssetmask + .long sys_setreuid16 /* 70 */ + .long sys_setregid16 + .long sys_sigsuspend + .long sys_sigpending + .long sys_sethostname + .long sys_setrlimit /* 75 */ + .long sys_old_getrlimit + .long sys_getrusage + .long sys_gettimeofday + .long sys_settimeofday + .long sys_getgroups16 /* 80 */ + .long sys_setgroups16 + .long sys_ni_syscall /* sys_oldselect */ + .long sys_symlink + .long sys_lstat + .long sys_readlink /* 85 */ + .long sys_uselib + .long sys_swapon + .long sys_reboot + .long old_readdir + .long old_mmap /* 90 */ + .long sys_munmap + .long sys_truncate + .long sys_ftruncate + .long sys_fchmod + .long sys_fchown16 /* 95 */ + .long sys_getpriority + .long sys_setpriority + .long sys_ni_syscall /* old profil syscall holder */ + .long sys_statfs + .long sys_fstatfs /* 100 */ + .long sys_ni_syscall /* ioperm */ + .long sys_socketcall /* Obsolete implementation of socket syscall */ + .long sys_syslog + .long sys_setitimer + .long sys_getitimer /* 105 */ + .long sys_newstat + .long sys_newlstat + .long sys_newfstat + .long sys_uname + .long sys_ni_syscall /* 110 */ /* iopl */ + .long sys_vhangup + .long sys_ni_syscall /* idle */ + .long sys_ni_syscall /* vm86old */ + .long sys_wait4 + .long sys_swapoff /* 115 */ + .long sys_sysinfo + .long sys_ipc /* Obsolete ipc syscall implementation */ + .long sys_fsync + .long sys_sigreturn + .long sys_clone /* 120 */ + .long sys_setdomainname + .long sys_newuname + .long sys_ni_syscall /* sys_modify_ldt */ + .long sys_adjtimex + .long sys_mprotect /* 125 */ + .long sys_sigprocmask + .long sys_ni_syscall /* old "create_module" */ + .long sys_init_module + .long sys_delete_module + .long sys_ni_syscall /* 130: old "get_kernel_syms" */ + .long sys_quotactl + .long sys_getpgid + .long sys_fchdir + .long sys_bdflush + .long sys_sysfs /* 135 */ + .long sys_personality + .long sys_ni_syscall /* for afs_syscall */ + .long sys_setfsuid16 + .long sys_setfsgid16 + .long sys_llseek /* 140 */ + .long sys_getdents + .long sys_select + .long sys_flock + .long sys_msync + .long sys_readv /* 145 */ + .long sys_writev + .long sys_getsid + .long sys_fdatasync + .long sys_sysctl + .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 + .long sys_sched_getscheduler + .long sys_sched_yield + .long sys_sched_get_priority_max + .long sys_sched_get_priority_min /* 160 */ + .long sys_sched_rr_get_interval + .long sys_nanosleep + .long sys_mremap + .long sys_setresuid16 + .long sys_getresuid16 /* 165 */ + .long sys_ni_syscall /* vm86 */ + .long sys_ni_syscall /* old "query_module" */ + .long sys_poll + .long sys_nfsservctl + .long sys_setresgid16 /* 170 */ + .long sys_getresgid16 + .long sys_prctl + .long sys_rt_sigreturn + .long sys_rt_sigaction + .long sys_rt_sigprocmask /* 175 */ + .long sys_rt_sigpending + .long sys_rt_sigtimedwait + .long sys_rt_sigqueueinfo + .long sys_rt_sigsuspend + .long sys_pread64 /* 180 */ + .long sys_pwrite64 + .long sys_chown16 + .long sys_getcwd + .long sys_capget + .long sys_capset /* 185 */ + .long sys_sigaltstack + .long sys_sendfile + .long sys_ni_syscall /* streams1 */ + .long sys_ni_syscall /* streams2 */ + .long sys_vfork /* 190 */ + .long sys_getrlimit + .long sys_mmap2 + .long sys_truncate64 + .long sys_ftruncate64 + .long sys_stat64 /* 195 */ + .long sys_lstat64 + .long sys_fstat64 + .long sys_lchown + .long sys_getuid + .long sys_getgid /* 200 */ + .long sys_geteuid + .long sys_getegid + .long sys_setreuid + .long sys_setregid + .long sys_getgroups /* 205 */ + .long sys_setgroups + .long sys_fchown + .long sys_setresuid + .long sys_getresuid + .long sys_setresgid /* 210 */ + .long sys_getresgid + .long sys_chown + .long sys_setuid + .long sys_setgid + .long sys_setfsuid /* 215 */ + .long sys_setfsgid + .long sys_pivot_root + .long sys_mincore + .long sys_madvise + /* Broken-out socket family (maintain backwards compatibility in syscall + numbering with 2.4) */ + .long sys_socket /* 220 */ + .long sys_bind + .long sys_connect + .long sys_listen + .long sys_accept + .long sys_getsockname /* 225 */ + .long sys_getpeername + .long sys_socketpair + .long sys_send + .long sys_sendto + .long sys_recv /* 230*/ + .long sys_recvfrom + .long sys_shutdown + .long sys_setsockopt + .long sys_getsockopt + .long sys_sendmsg /* 235 */ + .long sys_recvmsg + /* Broken-out IPC family (maintain backwards compatibility in syscall + numbering with 2.4) */ + .long sys_semop + .long sys_semget + .long sys_semctl + .long sys_msgsnd /* 240 */ + .long sys_msgrcv + .long sys_msgget + .long sys_msgctl + .long sys_shmat + .long sys_shmdt /* 245 */ + .long sys_shmget + .long sys_shmctl + /* Rest of syscalls listed in 2.4 i386 unistd.h */ + .long sys_getdents64 + .long sys_fcntl64 + .long sys_ni_syscall /* 250 reserved for TUX */ + .long sys_ni_syscall /* Reserved for Security */ + .long sys_gettid + .long sys_readahead + .long sys_setxattr + .long sys_lsetxattr /* 255 */ + .long sys_fsetxattr + .long sys_getxattr + .long sys_lgetxattr + .long sys_fgetxattr + .long sys_listxattr /* 260 */ + .long sys_llistxattr + .long sys_flistxattr + .long sys_removexattr + .long sys_lremovexattr + .long sys_fremovexattr /* 265 */ + .long sys_tkill + .long sys_sendfile64 + .long sys_futex + .long sys_sched_setaffinity + .long sys_sched_getaffinity /* 270 */ + .long sys_ni_syscall + .long sys_ni_syscall + .long sys_io_setup + .long sys_io_destroy + .long sys_io_getevents /* 275 */ + .long sys_io_submit + .long sys_io_cancel + .long sys_fadvise64 + .long sys_ni_syscall + .long sys_exit_group /* 280 */ + /* Rest of new 2.6 syscalls */ + .long sys_lookup_dcookie + .long sys_epoll_create + .long sys_epoll_ctl + .long sys_epoll_wait + .long sys_remap_file_pages /* 285 */ + .long sys_set_tid_address + .long sys_timer_create + .long sys_timer_settime + .long sys_timer_gettime + .long sys_timer_getoverrun /* 290 */ + .long sys_timer_delete + .long sys_clock_settime + .long sys_clock_gettime + .long sys_clock_getres + .long sys_clock_nanosleep /* 295 */ + .long sys_statfs64 + .long sys_fstatfs64 + .long sys_tgkill + .long sys_utimes + .long sys_fadvise64_64 /* 300 */ + .long sys_ni_syscall /* Reserved for vserver */ + .long sys_ni_syscall /* Reserved for mbind */ + .long sys_ni_syscall /* get_mempolicy */ + .long sys_ni_syscall /* set_mempolicy */ + .long sys_mq_open /* 305 */ + .long sys_mq_unlink + .long sys_mq_timedsend + .long sys_mq_timedreceive + .long sys_mq_notify + .long sys_mq_getsetattr /* 310 */ + .long sys_ni_syscall /* Reserved for kexec */ + .long sys_waitid + .long sys_add_key + .long sys_request_key + .long sys_keyctl /* 315 */ + .long sys_ioprio_set + .long sys_ioprio_get + .long sys_inotify_init + .long sys_inotify_add_watch + .long sys_inotify_rm_watch /* 320 */ + .long sys_ni_syscall + .long sys_migrate_pages + .long sys_openat + .long sys_mkdirat + .long sys_mknodat /* 325 */ + .long sys_fchownat + .long sys_futimesat + .long sys_fstatat64 + .long sys_unlinkat + .long sys_renameat /* 330 */ + .long sys_linkat + .long sys_symlinkat + .long sys_readlinkat + .long sys_fchmodat + .long sys_faccessat /* 335 */ + .long sys_pselect6 + .long sys_ppoll + .long sys_unshare + .long sys_set_robust_list + .long sys_get_robust_list /* 340 */ + .long sys_splice + .long sys_sync_file_range + .long sys_tee + .long sys_vmsplice + .long sys_move_pages /* 345 */ + .long sys_getcpu + .long sys_epoll_pwait + .long sys_utimensat + .long sys_signalfd + .long sys_timerfd /* 350 */ + .long sys_eventfd + .long sys_fallocate diff -puN arch/sh/kernel/time.c~git-sh /dev/null --- a/arch/sh/kernel/time.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * arch/sh/kernel/time.c - * - * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka - * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2002 - 2007 Paul Mundt - * Copyright (C) 2002 M. R. Brown - * - * Some code taken from i386 version. - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct sys_timer *sys_timer; - -/* Move this somewhere more sensible.. */ -DEFINE_SPINLOCK(rtc_lock); -EXPORT_SYMBOL(rtc_lock); - -/* Dummy RTC ops */ -static void null_rtc_get_time(struct timespec *tv) -{ - tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0); - tv->tv_nsec = 0; -} - -static int null_rtc_set_time(const time_t secs) -{ - return 0; -} - -/* - * Null high precision timer functions for systems lacking one. - */ -static cycle_t null_hpt_read(void) -{ - return 0; -} - -void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; -int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; - -#ifndef CONFIG_GENERIC_TIME -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long usec, sec; - - do { - /* - * Turn off IRQs when grabbing xtime_lock, so that - * the sys_timer get_offset code doesn't have to handle it. - */ - seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = get_timer_offset(); - sec = xtime.tv_sec; - usec += xtime.tv_nsec / NSEC_PER_USEC; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - 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 -= get_timer_offset() * NSEC_PER_USEC; - - 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); -#endif /* !CONFIG_GENERIC_TIME */ - -#ifndef CONFIG_GENERIC_CLOCKEVENTS -/* last time the RTC clock got updated */ -static long last_rtc_update; - -/* - * handle_timer_tick() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -void handle_timer_tick(void) -{ - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - if (current->pid) - profile_tick(CPU_PROFILING); - -#ifdef CONFIG_HEARTBEAT - if (sh_mv.mv_heartbeat != NULL) - sh_mv.mv_heartbeat(); -#endif - - /* - * If we have an externally synchronized Linux clock, then update - * RTC 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 (rtc_sh_set_time(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - /* do it again in 60s */ - last_rtc_update = xtime.tv_sec - 600; - } -} -#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ - -#ifdef CONFIG_PM -int timer_suspend(struct sys_device *dev, pm_message_t state) -{ - struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); - - sys_timer->ops->stop(); - - return 0; -} - -int timer_resume(struct sys_device *dev) -{ - struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); - - sys_timer->ops->start(); - - return 0; -} -#else -#define timer_suspend NULL -#define timer_resume NULL -#endif - -static struct sysdev_class timer_sysclass = { - .name = "timer", - .suspend = timer_suspend, - .resume = timer_resume, -}; - -static int __init timer_init_sysfs(void) -{ - int ret = sysdev_class_register(&timer_sysclass); - if (ret != 0) - return ret; - - sys_timer->dev.cls = &timer_sysclass; - return sysdev_register(&sys_timer->dev); -} -device_initcall(timer_init_sysfs); - -void (*board_time_init)(void); - -/* - * Shamelessly based on the MIPS and Sparc64 work. - */ -static unsigned long timer_ticks_per_nsec_quotient __read_mostly; -unsigned long sh_hpt_frequency = 0; - -#define NSEC_PER_CYC_SHIFT 10 - -struct clocksource clocksource_sh = { - .name = "SuperH", - .rating = 200, - .mask = CLOCKSOURCE_MASK(32), - .read = null_hpt_read, - .shift = 16, - .flags = CLOCK_SOURCE_IS_CONTINUOUS, -}; - -static void __init init_sh_clocksource(void) -{ - if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) - return; - - clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, - clocksource_sh.shift); - - timer_ticks_per_nsec_quotient = - clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); - - clocksource_register(&clocksource_sh); -} - -#ifdef CONFIG_GENERIC_TIME -unsigned long long sched_clock(void) -{ - unsigned long long ticks = clocksource_sh.read(); - return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; -} -#endif - -void __init time_init(void) -{ - if (board_time_init) - board_time_init(); - - clk_init(); - - rtc_sh_get_time(&xtime); - set_normalized_timespec(&wall_to_monotonic, - -xtime.tv_sec, -xtime.tv_nsec); - - /* - * Find the timer to use as the system timer, it will be - * initialized for us. - */ - sys_timer = get_sys_timer(); - printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); - - if (sys_timer->ops->read) - clocksource_sh.read = sys_timer->ops->read; - - init_sh_clocksource(); - - if (sh_hpt_frequency) - printk("Using %lu.%03lu MHz high precision timer.\n", - ((sh_hpt_frequency + 500) / 1000) / 1000, - ((sh_hpt_frequency + 500) / 1000) % 1000); - -#if defined(CONFIG_SH_KGDB) - /* - * Set up kgdb as requested. We do it here because the serial - * init uses the timer vars we just set up for figuring baud. - */ - kgdb_init(); -#endif -} diff -puN /dev/null arch/sh/kernel/time_32.c --- /dev/null +++ a/arch/sh/kernel/time_32.c @@ -0,0 +1,269 @@ +/* + * arch/sh/kernel/time.c + * + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2002 - 2007 Paul Mundt + * Copyright (C) 2002 M. R. Brown + * + * Some code taken from i386 version. + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sys_timer *sys_timer; + +/* Move this somewhere more sensible.. */ +DEFINE_SPINLOCK(rtc_lock); +EXPORT_SYMBOL(rtc_lock); + +/* Dummy RTC ops */ +static void null_rtc_get_time(struct timespec *tv) +{ + tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0); + tv->tv_nsec = 0; +} + +static int null_rtc_set_time(const time_t secs) +{ + return 0; +} + +/* + * Null high precision timer functions for systems lacking one. + */ +static cycle_t null_hpt_read(void) +{ + return 0; +} + +void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; +int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; + +#ifndef CONFIG_GENERIC_TIME +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + unsigned long seq; + unsigned long usec, sec; + + do { + /* + * Turn off IRQs when grabbing xtime_lock, so that + * the sys_timer get_offset code doesn't have to handle it. + */ + seq = read_seqbegin_irqsave(&xtime_lock, flags); + usec = get_timer_offset(); + sec = xtime.tv_sec; + usec += xtime.tv_nsec / NSEC_PER_USEC; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); + + 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 -= get_timer_offset() * NSEC_PER_USEC; + + 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); +#endif /* !CONFIG_GENERIC_TIME */ + +#ifndef CONFIG_GENERIC_CLOCKEVENTS +/* last time the RTC clock got updated */ +static long last_rtc_update; + +/* + * handle_timer_tick() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +void handle_timer_tick(void) +{ + do_timer(1); +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif + if (current->pid) + profile_tick(CPU_PROFILING); + +#ifdef CONFIG_HEARTBEAT + if (sh_mv.mv_heartbeat != NULL) + sh_mv.mv_heartbeat(); +#endif + + /* + * If we have an externally synchronized Linux clock, then update + * RTC 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 (rtc_sh_set_time(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + /* do it again in 60s */ + last_rtc_update = xtime.tv_sec - 600; + } +} +#endif /* !CONFIG_GENERIC_CLOCKEVENTS */ + +#ifdef CONFIG_PM +int timer_suspend(struct sys_device *dev, pm_message_t state) +{ + struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); + + sys_timer->ops->stop(); + + return 0; +} + +int timer_resume(struct sys_device *dev) +{ + struct sys_timer *sys_timer = container_of(dev, struct sys_timer, dev); + + sys_timer->ops->start(); + + return 0; +} +#else +#define timer_suspend NULL +#define timer_resume NULL +#endif + +static struct sysdev_class timer_sysclass = { + set_kset_name("timer"), + .suspend = timer_suspend, + .resume = timer_resume, +}; + +static int __init timer_init_sysfs(void) +{ + int ret = sysdev_class_register(&timer_sysclass); + if (ret != 0) + return ret; + + sys_timer->dev.cls = &timer_sysclass; + return sysdev_register(&sys_timer->dev); +} +device_initcall(timer_init_sysfs); + +void (*board_time_init)(void); + +/* + * Shamelessly based on the MIPS and Sparc64 work. + */ +static unsigned long timer_ticks_per_nsec_quotient __read_mostly; +unsigned long sh_hpt_frequency = 0; + +#define NSEC_PER_CYC_SHIFT 10 + +struct clocksource clocksource_sh = { + .name = "SuperH", + .rating = 200, + .mask = CLOCKSOURCE_MASK(32), + .read = null_hpt_read, + .shift = 16, + .flags = CLOCK_SOURCE_IS_CONTINUOUS, +}; + +static void __init init_sh_clocksource(void) +{ + if (!sh_hpt_frequency || clocksource_sh.read == null_hpt_read) + return; + + clocksource_sh.mult = clocksource_hz2mult(sh_hpt_frequency, + clocksource_sh.shift); + + timer_ticks_per_nsec_quotient = + clocksource_hz2mult(sh_hpt_frequency, NSEC_PER_CYC_SHIFT); + + clocksource_register(&clocksource_sh); +} + +#ifdef CONFIG_GENERIC_TIME +unsigned long long sched_clock(void) +{ + unsigned long long ticks = clocksource_sh.read(); + return (ticks * timer_ticks_per_nsec_quotient) >> NSEC_PER_CYC_SHIFT; +} +#endif + +void __init time_init(void) +{ + if (board_time_init) + board_time_init(); + + clk_init(); + + rtc_sh_get_time(&xtime); + set_normalized_timespec(&wall_to_monotonic, + -xtime.tv_sec, -xtime.tv_nsec); + + /* + * Find the timer to use as the system timer, it will be + * initialized for us. + */ + sys_timer = get_sys_timer(); + printk(KERN_INFO "Using %s for system timer\n", sys_timer->name); + + if (sys_timer->ops->read) + clocksource_sh.read = sys_timer->ops->read; + + init_sh_clocksource(); + + if (sh_hpt_frequency) + printk("Using %lu.%03lu MHz high precision timer.\n", + ((sh_hpt_frequency + 500) / 1000) / 1000, + ((sh_hpt_frequency + 500) / 1000) % 1000); + +#if defined(CONFIG_SH_KGDB) + /* + * Set up kgdb as requested. We do it here because the serial + * init uses the timer vars we just set up for figuring baud. + */ + kgdb_init(); +#endif +} diff -puN /dev/null arch/sh/kernel/time_64.c --- /dev/null +++ a/arch/sh/kernel/time_64.c @@ -0,0 +1,519 @@ +/* + * arch/sh/kernel/time_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * Copyright (C) 2003 Richard Curnow + * + * Original TMU/RTC code taken from sh version. + * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka + * Some code taken from i386 version. + * Copyright (C) 1991, 1992, 1995 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* required by inline __asm__ stmt. */ +#include +#include +#include +#include +#include + +#define TMU_TOCR_INIT 0x00 +#define TMU0_TCR_INIT 0x0020 +#define TMU_TSTR_INIT 1 +#define TMU_TSTR_OFF 0 + +/* Real Time Clock */ +#define RTC_BLOCK_OFF 0x01040000 +#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF +#define RTC_RCR1_CIE 0x10 /* Carry Interrupt Enable */ +#define RTC_RCR1 (rtc_base + 0x38) + +/* Clock, Power and Reset Controller */ +#define CPRC_BLOCK_OFF 0x01010000 +#define CPRC_BASE PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF + +#define FRQCR (cprc_base+0x0) +#define WTCSR (cprc_base+0x0018) +#define STBCR (cprc_base+0x0030) + +/* Time Management Unit */ +#define TMU_BLOCK_OFF 0x01020000 +#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF +#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0) +#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1) +#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2) + +#define TMU_TOCR tmu_base+0x0 /* Byte access */ +#define TMU_TSTR tmu_base+0x4 /* Byte access */ + +#define TMU0_TCOR TMU0_BASE+0x0 /* Long access */ +#define TMU0_TCNT TMU0_BASE+0x4 /* Long access */ +#define TMU0_TCR TMU0_BASE+0x8 /* Word access */ + +#define TICK_SIZE (tick_nsec / 1000) + +static unsigned long tmu_base, rtc_base; +unsigned long cprc_base; + +/* Variables to allow interpolation of time of day to resolution better than a + * jiffy. */ + +/* This is effectively protected by xtime_lock */ +static unsigned long ctc_last_interrupt; +static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */ + +#define CTC_JIFFY_SCALE_SHIFT 40 + +/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */ +static unsigned long long scaled_recip_ctc_ticks_per_jiffy; + +/* Estimate number of microseconds that have elapsed since the last timer tick, + by scaling the delta that has occurred in the CTC register. + + WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at + the CPU clock rate. If the CPU sleeps, the CTC stops counting. Bear this + in mind if enabling SLEEP_WORKS in process.c. In that case, this algorithm + probably needs to use TMU.TCNT0 instead. This will work even if the CPU is + sleeping, though will be coarser. + + FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime + is running or if the freq or tick arguments of adjtimex are modified after + we have calibrated the scaling factor? This will result in either a jump at + the end of a tick period, or a wrap backwards at the start of the next one, + if the application is reading the time of day often enough. I think we + ought to do better than this. For this reason, usecs_per_jiffy is left + separated out in the calculation below. This allows some future hook into + the adjtime-related stuff in kernel/timer.c to remove this hazard. + +*/ + +static unsigned long usecs_since_tick(void) +{ + unsigned long long current_ctc; + long ctc_ticks_since_interrupt; + unsigned long long ull_ctc_ticks_since_interrupt; + unsigned long result; + + unsigned long long mul1_out; + unsigned long long mul1_out_high; + unsigned long long mul2_out_low, mul2_out_high; + + /* Read CTC register */ + asm ("getcon cr62, %0" : "=r" (current_ctc)); + /* Note, the CTC counts down on each CPU clock, not up. + Note(2), use long type to get correct wraparound arithmetic when + the counter crosses zero. */ + ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc; + ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt; + + /* Inline assembly to do 32x32x32->64 multiplier */ + asm volatile ("mulu.l %1, %2, %0" : + "=r" (mul1_out) : + "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy)); + + mul1_out_high = mul1_out >> 32; + + asm volatile ("mulu.l %1, %2, %0" : + "=r" (mul2_out_low) : + "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy)); + +#if 1 + asm volatile ("mulu.l %1, %2, %0" : + "=r" (mul2_out_high) : + "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy)); +#endif + + result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT); + + return result; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long flags; + unsigned long seq; + unsigned long usec, sec; + + do { + seq = read_seqbegin_irqsave(&xtime_lock, flags); + usec = usecs_since_tick(); + sec = xtime.tv_sec; + usec += xtime.tv_nsec / 1000; + } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); + + while (usec >= 1000000) { + usec -= 1000000; + sec++; + } + + tv->tv_sec = sec; + tv->tv_usec = usec; +} + +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 -= 1000 * usecs_since_tick(); + + 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); + +/* Dummy RTC ops */ +static void null_rtc_get_time(struct timespec *tv) +{ + tv->tv_sec = mktime(2000, 1, 1, 0, 0, 0); + tv->tv_nsec = 0; +} + +static int null_rtc_set_time(const time_t secs) +{ + return 0; +} + +void (*rtc_sh_get_time)(struct timespec *) = null_rtc_get_time; +int (*rtc_sh_set_time)(const time_t) = null_rtc_set_time; + +/* last time the RTC clock got updated */ +static long last_rtc_update; + +/* + * timer_interrupt() needs to keep up the real-time clock, + * as well as call the "do_timer()" routine every clocktick + */ +static inline void do_timer_interrupt(void) +{ + unsigned long long current_ctc; + asm ("getcon cr62, %0" : "=r" (current_ctc)); + ctc_last_interrupt = (unsigned long) current_ctc; + + do_timer(1); +#ifndef CONFIG_SMP + update_process_times(user_mode(get_irq_regs())); +#endif + if (current->pid) + profile_tick(CPU_PROFILING); + +#ifdef CONFIG_HEARTBEAT + if (sh_mv.mv_heartbeat != NULL) + sh_mv.mv_heartbeat(); +#endif + + /* + * If we have an externally synchronized Linux clock, then update + * RTC 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 (rtc_sh_set_time(xtime.tv_sec) == 0) + last_rtc_update = xtime.tv_sec; + else + /* do it again in 60 s */ + last_rtc_update = xtime.tv_sec - 600; + } +} + +/* + * This is the same as the above, except we _also_ save the current + * Time Stamp Counter value at the time of the timer interrupt, so that + * we later on can estimate the time of day more exactly. + */ +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + unsigned long timer_status; + + /* Clear UNF bit */ + timer_status = ctrl_inw(TMU0_TCR); + timer_status &= ~0x100; + ctrl_outw(timer_status, TMU0_TCR); + + /* + * 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_lock(&xtime_lock); + do_timer_interrupt(); + write_unlock(&xtime_lock); + + return IRQ_HANDLED; +} + + +static __init unsigned int get_cpu_hz(void) +{ + unsigned int count; + unsigned long __dummy; + unsigned long ctc_val_init, ctc_val; + + /* + ** Regardless the toolchain, force the compiler to use the + ** arbitrary register r3 as a clock tick counter. + ** NOTE: r3 must be in accordance with sh64_rtc_interrupt() + */ + register unsigned long long __rtc_irq_flag __asm__ ("r3"); + + local_irq_enable(); + do {} while (ctrl_inb(rtc_base) != 0); + ctrl_outb(RTC_RCR1_CIE, RTC_RCR1); /* Enable carry interrupt */ + + /* + * r3 is arbitrary. CDC does not support "=z". + */ + ctc_val_init = 0xffffffff; + ctc_val = ctc_val_init; + + asm volatile("gettr tr0, %1\n\t" + "putcon %0, " __CTC "\n\t" + "and %2, r63, %2\n\t" + "pta $+4, tr0\n\t" + "beq/l %2, r63, tr0\n\t" + "ptabs %1, tr0\n\t" + "getcon " __CTC ", %0\n\t" + : "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag) + : "0" (0)); + local_irq_disable(); + /* + * SH-3: + * CPU clock = 4 stages * loop + * tst rm,rm if id ex + * bt/s 1b if id ex + * add #1,rd if id ex + * (if) pipe line stole + * tst rm,rm if id ex + * .... + * + * + * SH-4: + * CPU clock = 6 stages * loop + * I don't know why. + * .... + * + * SH-5: + * Use CTC register to count. This approach returns the right value + * even if the I-cache is disabled (e.g. whilst debugging.) + * + */ + + count = ctc_val_init - ctc_val; /* CTC counts down */ + + /* + * This really is count by the number of clock cycles + * by the ratio between a complete R64CNT + * wrap-around (128) and CUI interrupt being raised (64). + */ + return count*2; +} + +static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id) +{ + struct pt_regs *regs = get_irq_regs(); + + ctrl_outb(0, RTC_RCR1); /* Disable Carry Interrupts */ + regs->regs[3] = 1; /* Using r3 */ + + return IRQ_HANDLED; +} + +static struct irqaction irq0 = { + .handler = timer_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "timer", +}; +static struct irqaction irq1 = { + .handler = sh64_rtc_interrupt, + .flags = IRQF_DISABLED, + .mask = CPU_MASK_NONE, + .name = "rtc", +}; + +void __init time_init(void) +{ + unsigned int cpu_clock, master_clock, bus_clock, module_clock; + unsigned long interval; + unsigned long frqcr, ifc, pfc; + static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 }; +#define bfc_table ifc_table /* Same */ +#define pfc_table ifc_table /* Same */ + + tmu_base = onchip_remap(TMU_BASE, 1024, "TMU"); + if (!tmu_base) { + panic("Unable to remap TMU\n"); + } + + rtc_base = onchip_remap(RTC_BASE, 1024, "RTC"); + if (!rtc_base) { + panic("Unable to remap RTC\n"); + } + + cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC"); + if (!cprc_base) { + panic("Unable to remap CPRC\n"); + } + + rtc_sh_get_time(&xtime); + + setup_irq(TIMER_IRQ, &irq0); + setup_irq(RTC_IRQ, &irq1); + + /* Check how fast it is.. */ + cpu_clock = get_cpu_hz(); + + /* Note careful order of operations to maintain reasonable precision and avoid overflow. */ + scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ)); + + free_irq(RTC_IRQ, NULL); + + printk("CPU clock: %d.%02dMHz\n", + (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); + { + unsigned short bfc; + frqcr = ctrl_inl(FRQCR); + ifc = ifc_table[(frqcr>> 6) & 0x0007]; + bfc = bfc_table[(frqcr>> 3) & 0x0007]; + pfc = pfc_table[(frqcr>> 12) & 0x0007]; + master_clock = cpu_clock * ifc; + bus_clock = master_clock/bfc; + } + + printk("Bus clock: %d.%02dMHz\n", + (bus_clock/1000000), (bus_clock % 1000000)/10000); + module_clock = master_clock/pfc; + printk("Module clock: %d.%02dMHz\n", + (module_clock/1000000), (module_clock % 1000000)/10000); + interval = (module_clock/(HZ*4)); + + printk("Interval = %ld\n", interval); + + current_cpu_data.cpu_clock = cpu_clock; + current_cpu_data.master_clock = master_clock; + current_cpu_data.bus_clock = bus_clock; + current_cpu_data.module_clock = module_clock; + + /* Start TMU0 */ + ctrl_outb(TMU_TSTR_OFF, TMU_TSTR); + ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); + ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); + ctrl_outl(interval, TMU0_TCOR); + ctrl_outl(interval, TMU0_TCNT); + ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); +} + +void enter_deep_standby(void) +{ + /* Disable watchdog timer */ + ctrl_outl(0xa5000000, WTCSR); + /* Configure deep standby on sleep */ + ctrl_outl(0x03, STBCR); + +#ifdef CONFIG_SH_ALPHANUMERIC + { + extern void mach_alphanum(int position, unsigned char value); + extern void mach_alphanum_brightness(int setting); + char halted[] = "Halted. "; + int i; + mach_alphanum_brightness(6); /* dimmest setting above off */ + for (i=0; i<8; i++) { + mach_alphanum(i, halted[i]); + } + asm __volatile__ ("synco"); + } +#endif + + asm __volatile__ ("sleep"); + asm __volatile__ ("synci"); + asm __volatile__ ("nop"); + asm __volatile__ ("nop"); + asm __volatile__ ("nop"); + asm __volatile__ ("nop"); + panic("Unexpected wakeup!\n"); +} + +static struct resource rtc_resources[] = { + [0] = { + /* RTC base, filled in by rtc_init */ + .flags = IORESOURCE_IO, + }, + [1] = { + /* Period IRQ */ + .start = IRQ_PRI, + .flags = IORESOURCE_IRQ, + }, + [2] = { + /* Carry IRQ */ + .start = IRQ_CUI, + .flags = IORESOURCE_IRQ, + }, + [3] = { + /* Alarm IRQ */ + .start = IRQ_ATI, + .flags = IORESOURCE_IRQ, + }, +}; + +static struct platform_device rtc_device = { + .name = "sh-rtc", + .id = -1, + .num_resources = ARRAY_SIZE(rtc_resources), + .resource = rtc_resources, +}; + +static int __init rtc_init(void) +{ + rtc_resources[0].start = rtc_base; + rtc_resources[0].end = rtc_resources[0].start + 0x58 - 1; + + return platform_device_register(&rtc_device); +} +device_initcall(rtc_init); diff -puN arch/sh/kernel/timers/timer-cmt.c~git-sh arch/sh/kernel/timers/timer-cmt.c --- a/arch/sh/kernel/timers/timer-cmt.c~git-sh +++ a/arch/sh/kernel/timers/timer-cmt.c @@ -31,7 +31,9 @@ #define cmt_clock_enable() do { ctrl_outb(ctrl_inb(STBCR3) & ~0x10, STBCR3); } while(0) #define CMT_CMCSR_INIT 0x0040 #define CMT_CMCSR_CALIB 0x0000 -#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \ + defined(CONFIG_CPU_SUBTYPE_SH7206) || \ + defined(CONFIG_CPU_SUBTYPE_SH7263) #define CMT_CMSTR 0xfffec000 #define CMT_CMCSR_0 0xfffec002 #define CMT_CMCNT_0 0xfffec004 diff -puN arch/sh/kernel/traps.c~git-sh arch/sh/kernel/traps.c --- a/arch/sh/kernel/traps.c~git-sh +++ a/arch/sh/kernel/traps.c @@ -1,947 +1,68 @@ -/* - * 'traps.c' handles hardware traps and faults after we have saved some - * state in 'entry.S'. - * - * SuperH version: Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2000 Philipp Rumpf - * Copyright (C) 2000 David Howells - * Copyright (C) 2002 - 2007 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include #include -#include -#include +#include +#include #include -#include - -#ifdef CONFIG_SH_KGDB -#include -#define CHK_REMOTE_DEBUG(regs) \ -{ \ - if (kgdb_debug_hook && !user_mode(regs))\ - (*kgdb_debug_hook)(regs); \ -} -#else -#define CHK_REMOTE_DEBUG(regs) -#endif - -#ifdef CONFIG_CPU_SH2 -# define TRAP_RESERVED_INST 4 -# define TRAP_ILLEGAL_SLOT_INST 6 -# define TRAP_ADDRESS_ERROR 9 -# ifdef CONFIG_CPU_SH2A -# define TRAP_DIVZERO_ERROR 17 -# define TRAP_DIVOVF_ERROR 18 -# endif -#else -#define TRAP_RESERVED_INST 12 -#define TRAP_ILLEGAL_SLOT_INST 13 -#endif - -static void dump_mem(const char *str, unsigned long bottom, unsigned long top) -{ - unsigned long p; - int i; - - printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); - - for (p = bottom & ~31; p < top; ) { - printk("%04lx: ", p & 0xffff); - - for (i = 0; i < 8; i++, p += 4) { - unsigned int val; - - if (p < bottom || p >= top) - printk(" "); - else { - if (__get_user(val, (unsigned int __user *)p)) { - printk("\n"); - return; - } - printk("%08x ", val); - } - } - printk("\n"); - } -} - -static DEFINE_SPINLOCK(die_lock); - -void die(const char * str, struct pt_regs * regs, long err) -{ - static int die_counter; - - oops_enter(); - - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - - printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); - - CHK_REMOTE_DEBUG(regs); - print_modules(); - show_regs(regs); - - printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm, - task_pid_nr(current), task_stack_page(current) + 1); - - if (!user_mode(regs) || in_interrupt()) - dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + - (unsigned long)task_stack_page(current)); - - bust_spinlocks(0); - add_taint(TAINT_DIE); - spin_unlock_irq(&die_lock); - - if (kexec_should_crash(current)) - crash_kexec(regs); - - if (in_interrupt()) - panic("Fatal exception in interrupt"); - - if (panic_on_oops) - panic("Fatal exception"); - - oops_exit(); - do_exit(SIGSEGV); -} - -static inline void die_if_kernel(const char *str, struct pt_regs *regs, - long err) -{ - if (!user_mode(regs)) - die(str, regs, err); -} - -/* - * try and fix up kernelspace address errors - * - userspace errors just cause EFAULT to be returned, resulting in SEGV - * - kernel/userspace interfaces cause a jump to an appropriate handler - * - other kernel errors are bad - * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault - */ -static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return 0; - } - die(str, regs, err); - } - return -EFAULT; -} - -/* - * handle an instruction that does an unaligned memory access by emulating the - * desired behaviour - * - note that PC _may not_ point to the faulting instruction - * (if that instruction is in a branch delay slot) - * - return 0 if emulation okay, -EFAULT on existential error - */ -static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) -{ - int ret, index, count; - unsigned long *rm, *rn; - unsigned char *src, *dst; - - index = (instruction>>8)&15; /* 0x0F00 */ - rn = ®s->regs[index]; - - index = (instruction>>4)&15; /* 0x00F0 */ - rm = ®s->regs[index]; - - count = 1<<(instruction&3); - - ret = -EFAULT; - switch (instruction>>12) { - case 0: /* mov.[bwl] to/from memory via r0+rn */ - if (instruction & 8) { - /* from memory */ - src = (unsigned char*) *rm; - src += regs->regs[0]; - dst = (unsigned char*) rn; - *(unsigned long*)dst = 0; - -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else - dst += 4-count; - - if (__copy_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif - } else { - /* to memory */ - src = (unsigned char*) rm; -#if !defined(__LITTLE_ENDIAN__) - src += 4-count; -#endif - dst = (unsigned char*) *rn; - dst += regs->regs[0]; - - if (copy_to_user(dst, src, count)) - goto fetch_fault; - } - ret = 0; - break; - - case 1: /* mov.l Rm,@(disp,Rn) */ - src = (unsigned char*) rm; - dst = (unsigned char*) *rn; - dst += (instruction&0x000F)<<2; - - if (copy_to_user(dst,src,4)) - goto fetch_fault; - ret = 0; - break; - - case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ - if (instruction & 4) - *rn -= count; - src = (unsigned char*) rm; - dst = (unsigned char*) *rn; -#if !defined(__LITTLE_ENDIAN__) - src += 4-count; -#endif - if (copy_to_user(dst, src, count)) - goto fetch_fault; - ret = 0; - break; - - case 5: /* mov.l @(disp,Rm),Rn */ - src = (unsigned char*) *rm; - src += (instruction&0x000F)<<2; - dst = (unsigned char*) rn; - *(unsigned long*)dst = 0; - - if (copy_from_user(dst,src,4)) - goto fetch_fault; - ret = 0; - break; - - case 6: /* mov.[bwl] from memory, possibly with post-increment */ - src = (unsigned char*) *rm; - if (instruction & 4) - *rm += count; - dst = (unsigned char*) rn; - *(unsigned long*)dst = 0; - -#ifdef __LITTLE_ENDIAN__ - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else - dst += 4-count; - - if (copy_from_user(dst, src, count)) - goto fetch_fault; - - if ((count == 2) && dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif - ret = 0; - break; - - case 8: - switch ((instruction&0xFF00)>>8) { - case 0x81: /* mov.w R0,@(disp,Rn) */ - src = (unsigned char*) ®s->regs[0]; -#if !defined(__LITTLE_ENDIAN__) - src += 2; -#endif - dst = (unsigned char*) *rm; /* called Rn in the spec */ - dst += (instruction&0x000F)<<1; - if (copy_to_user(dst, src, 2)) - goto fetch_fault; - ret = 0; - break; - - case 0x85: /* mov.w @(disp,Rm),R0 */ - src = (unsigned char*) *rm; - src += (instruction&0x000F)<<1; - dst = (unsigned char*) ®s->regs[0]; - *(unsigned long*)dst = 0; - -#if !defined(__LITTLE_ENDIAN__) - dst += 2; -#endif - - if (copy_from_user(dst, src, 2)) - goto fetch_fault; - -#ifdef __LITTLE_ENDIAN__ - if (dst[1] & 0x80) { - dst[2] = 0xff; - dst[3] = 0xff; - } -#else - if (dst[2] & 0x80) { - dst[0] = 0xff; - dst[1] = 0xff; - } -#endif - ret = 0; - break; - } - break; - } - return ret; - - fetch_fault: - /* Argh. Address not only misaligned but also non-existent. - * Raise an EFAULT and see if it's trapped - */ - return die_if_no_fixup("Fault in unaligned fixup", regs, 0); -} - -/* - * emulate the instruction in the delay slot - * - fetches the instruction from PC+2 - */ -static inline int handle_unaligned_delayslot(struct pt_regs *regs) +#ifdef CONFIG_BUG +static void handle_BUG(struct pt_regs *regs) { - u16 instruction; - - if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) { - /* the instruction-fetch faulted */ - if (user_mode(regs)) - return -EFAULT; - - /* kernel */ - die("delay-slot-insn faulting in handle_unaligned_delayslot", - regs, 0); + enum bug_trap_type tt; + tt = report_bug(regs->pc, regs); + if (tt == BUG_TRAP_TYPE_WARN) { + regs->pc += instruction_size(regs->pc); + return; } - return handle_unaligned_ins(instruction,regs); + die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); } -/* - * handle an instruction that does an unaligned memory access - * - have to be careful of branch delay-slot instructions that fault - * SH3: - * - if the branch would be taken PC points to the branch - * - if the branch would not be taken, PC points to delay-slot - * SH4: - * - PC always points to delayed branch - * - return 0 if handled, -EFAULT if failed (may not return if in kernel) - */ - -/* Macros to determine offset from current PC for branch instructions */ -/* Explicit type coercion is used to force sign extension where needed */ -#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) -#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) - -/* - * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit - * opcodes.. - */ -#ifndef CONFIG_CPU_SH2A -static int handle_unaligned_notify_count = 10; - -static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) +int is_valid_bugaddr(unsigned long addr) { - u_int rm; - int ret, index; - - index = (instruction>>8)&15; /* 0x0F00 */ - rm = regs->regs[index]; - - /* shout about the first ten userspace fixups */ - if (user_mode(regs) && handle_unaligned_notify_count>0) { - handle_unaligned_notify_count--; - - printk(KERN_NOTICE "Fixing up unaligned userspace access " - "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", - current->comm, task_pid_nr(current), - (u16 *)regs->pc, instruction); - } - - ret = -EFAULT; - switch (instruction&0xF000) { - case 0x0000: - if (instruction==0x000B) { - /* rts */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc = regs->pr; - } - else if ((instruction&0x00FF)==0x0023) { - /* braf @Rm */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc += rm + 4; - } - else if ((instruction&0x00FF)==0x0003) { - /* bsrf @Rm */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) { - regs->pr = regs->pc + 4; - regs->pc += rm + 4; - } - } - else { - /* mov.[bwl] to/from memory via r0+rn */ - goto simple; - } - break; - - case 0x1000: /* mov.l Rm,@(disp,Rn) */ - goto simple; - - case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */ - goto simple; - - case 0x4000: - if ((instruction&0x00FF)==0x002B) { - /* jmp @Rm */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc = rm; - } - else if ((instruction&0x00FF)==0x000B) { - /* jsr @Rm */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) { - regs->pr = regs->pc + 4; - regs->pc = rm; - } - } - else { - /* mov.[bwl] to/from memory via r0+rn */ - goto simple; - } - break; - - case 0x5000: /* mov.l @(disp,Rm),Rn */ - goto simple; - - case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */ - goto simple; - - case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */ - switch (instruction&0x0F00) { - case 0x0100: /* mov.w R0,@(disp,Rm) */ - goto simple; - case 0x0500: /* mov.w @(disp,Rm),R0 */ - goto simple; - case 0x0B00: /* bf lab - no delayslot*/ - break; - case 0x0F00: /* bf/s lab */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) { -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) - if ((regs->sr & 0x00000001) != 0) - regs->pc += 4; /* next after slot */ - else -#endif - regs->pc += SH_PC_8BIT_OFFSET(instruction); - } - break; - case 0x0900: /* bt lab - no delayslot */ - break; - case 0x0D00: /* bt/s lab */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) { -#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) - if ((regs->sr & 0x00000001) == 0) - regs->pc += 4; /* next after slot */ - else -#endif - regs->pc += SH_PC_8BIT_OFFSET(instruction); - } - break; - } - break; - - case 0xA000: /* bra label */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) - regs->pc += SH_PC_12BIT_OFFSET(instruction); - break; - - case 0xB000: /* bsr label */ - ret = handle_unaligned_delayslot(regs); - if (ret==0) { - regs->pr = regs->pc + 4; - regs->pc += SH_PC_12BIT_OFFSET(instruction); - } - break; - } - return ret; - - /* handle non-delay-slot instruction */ - simple: - ret = handle_unaligned_ins(instruction,regs); - if (ret==0) - regs->pc += instruction_size(instruction); - return ret; + return addr >= PAGE_OFFSET; } -#endif /* CONFIG_CPU_SH2A */ - -#ifdef CONFIG_CPU_HAS_SR_RB -#define lookup_exception_vector(x) \ - __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x))) -#else -#define lookup_exception_vector(x) \ - __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x))) #endif /* - * Handle various address error exceptions: - * - instruction address error: - * misaligned PC - * PC >= 0x80000000 in user mode - * - data address error (read and write) - * misaligned data access - * access to >= 0x80000000 is user mode - * Unfortuntaly we can't distinguish between instruction address error - * and data address errors caused by read accesses. + * Generic trap handler. */ -asmlinkage void do_address_error(struct pt_regs *regs, - unsigned long writeaccess, - unsigned long address) +BUILD_TRAP_HANDLER(debug) { - unsigned long error_code = 0; - mm_segment_t oldfs; - siginfo_t info; -#ifndef CONFIG_CPU_SH2A - u16 instruction; - int tmp; -#endif + TRAP_HANDLER_DECL; - /* Intentional ifdef */ -#ifdef CONFIG_CPU_HAS_SR_RB - lookup_exception_vector(error_code); -#endif + /* Rewind */ + regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); - oldfs = get_fs(); - - if (user_mode(regs)) { - int si_code = BUS_ADRERR; - - local_irq_enable(); - - /* bad PC is not something we can fix */ - if (regs->pc & 1) { - si_code = BUS_ADRALN; - goto uspace_segv; - } - -#ifndef CONFIG_CPU_SH2A - set_fs(USER_DS); - if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { - /* Argh. Fault on the instruction itself. - This should never happen non-SMP - */ - set_fs(oldfs); - goto uspace_segv; - } - - tmp = handle_unaligned_access(instruction, regs); - set_fs(oldfs); - - if (tmp==0) - return; /* sorted */ -#endif - -uspace_segv: - printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " - "access (PC %lx PR %lx)\n", current->comm, regs->pc, - regs->pr); - - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = si_code; - info.si_addr = (void __user *)address; - force_sig_info(SIGBUS, &info, current); - } else { - if (regs->pc & 1) - die("unaligned program counter", regs, error_code); - -#ifndef CONFIG_CPU_SH2A - set_fs(KERNEL_DS); - if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { - /* Argh. Fault on the instruction itself. - This should never happen non-SMP - */ - set_fs(oldfs); - die("insn faulting in do_address_error", regs, 0); - } - - handle_unaligned_access(instruction, regs); - set_fs(oldfs); -#else - printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " - "access\n", current->comm); + if (notify_die(DIE_TRAP, "debug trap", regs, 0, vec & 0xff, + SIGTRAP) == NOTIFY_STOP) + return; - force_sig(SIGSEGV, current); -#endif - } + force_sig(SIGTRAP, current); } -#ifdef CONFIG_SH_DSP /* - * SH-DSP support gerg@snapgear.com. + * Special handler for BUG() traps. */ -int is_dsp_inst(struct pt_regs *regs) -{ - unsigned short inst = 0; - - /* - * Safe guard if DSP mode is already enabled or we're lacking - * the DSP altogether. - */ - if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP)) - return 0; - - get_user(inst, ((unsigned short *) regs->pc)); - - inst &= 0xf000; - - /* Check for any type of DSP or support instruction */ - if ((inst == 0xf000) || (inst == 0x4000)) - return 1; - - return 0; -} -#else -#define is_dsp_inst(regs) (0) -#endif /* CONFIG_SH_DSP */ - -#ifdef CONFIG_CPU_SH2A -asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) +BUILD_TRAP_HANDLER(bug) { - siginfo_t info; - - switch (r4) { - case TRAP_DIVZERO_ERROR: - info.si_code = FPE_INTDIV; - break; - case TRAP_DIVOVF_ERROR: - info.si_code = FPE_INTOVF; - break; - } + TRAP_HANDLER_DECL; - force_sig_info(SIGFPE, &info, current); -} -#endif - -/* arch/sh/kernel/cpu/sh4/fpu.c */ -extern int do_fpu_inst(unsigned short, struct pt_regs *); -extern asmlinkage void do_fpu_state_restore(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, struct pt_regs __regs); - -asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - unsigned long error_code; - struct task_struct *tsk = current; - -#ifdef CONFIG_SH_FPU_EMU - unsigned short inst = 0; - int err; - - get_user(inst, (unsigned short*)regs->pc); - - err = do_fpu_inst(inst, regs); - if (!err) { - regs->pc += instruction_size(inst); - return; - } - /* not a FPU inst. */ -#endif + /* Rewind */ + regs->pc -= instruction_size(ctrl_inw(regs->pc - 4)); -#ifdef CONFIG_SH_DSP - /* Check if it's a DSP instruction */ - if (is_dsp_inst(regs)) { - /* Enable DSP mode, and restart instruction. */ - regs->sr |= SR_DSP; + if (notify_die(DIE_TRAP, "bug trap", regs, 0, TRAPA_BUG_OPCODE & 0xff, + SIGTRAP) == NOTIFY_STOP) return; - } -#endif - - lookup_exception_vector(error_code); - - local_irq_enable(); - CHK_REMOTE_DEBUG(regs); - force_sig(SIGILL, tsk); - die_if_no_fixup("reserved instruction", regs, error_code); -} - -#ifdef CONFIG_SH_FPU_EMU -static int emulate_branch(unsigned short inst, struct pt_regs* regs) -{ - /* - * bfs: 8fxx: PC+=d*2+4; - * bts: 8dxx: PC+=d*2+4; - * bra: axxx: PC+=D*2+4; - * bsr: bxxx: PC+=D*2+4 after PR=PC+4; - * braf:0x23: PC+=Rn*2+4; - * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4; - * jmp: 4x2b: PC=Rn; - * jsr: 4x0b: PC=Rn after PR=PC+4; - * rts: 000b: PC=PR; - */ - if ((inst & 0xfd00) == 0x8d00) { - regs->pc += SH_PC_8BIT_OFFSET(inst); - return 0; - } - - if ((inst & 0xe000) == 0xa000) { - regs->pc += SH_PC_12BIT_OFFSET(inst); - return 0; - } - - if ((inst & 0xf0df) == 0x0003) { - regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; - return 0; - } - - if ((inst & 0xf0df) == 0x400b) { - regs->pc = regs->regs[(inst & 0x0f00) >> 8]; - return 0; - } - - if ((inst & 0xffff) == 0x000b) { - regs->pc = regs->pr; - return 0; - } - - return 1; -} -#endif - -asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - unsigned long error_code; - struct task_struct *tsk = current; -#ifdef CONFIG_SH_FPU_EMU - unsigned short inst = 0; - - get_user(inst, (unsigned short *)regs->pc + 1); - if (!do_fpu_inst(inst, regs)) { - get_user(inst, (unsigned short *)regs->pc); - if (!emulate_branch(inst, regs)) - return; - /* fault in branch.*/ - } - /* not a FPU inst. */ -#endif - - lookup_exception_vector(error_code); - - local_irq_enable(); - CHK_REMOTE_DEBUG(regs); - force_sig(SIGILL, tsk); - die_if_no_fixup("illegal slot instruction", regs, error_code); -} - -asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs) -{ - struct pt_regs *regs = RELOC_HIDE(&__regs, 0); - long ex; - - lookup_exception_vector(ex); - die_if_kernel("exception", regs, ex); -} - -#if defined(CONFIG_SH_STANDARD_BIOS) -void *gdb_vbr_vector; - -static inline void __init gdb_vbr_init(void) -{ - register unsigned long vbr; - - /* - * Read the old value of the VBR register to initialise - * the vector through which debug and BIOS traps are - * delegated by the Linux trap handler. - */ - asm volatile("stc vbr, %0" : "=r" (vbr)); - - gdb_vbr_vector = (void *)(vbr + 0x100); - printk("Setting GDB trap vector to 0x%08lx\n", - (unsigned long)gdb_vbr_vector); -} -#endif - -void __cpuinit per_cpu_trap_init(void) -{ - extern void *vbr_base; - -#ifdef CONFIG_SH_STANDARD_BIOS - if (raw_smp_processor_id() == 0) - gdb_vbr_init(); -#endif - - /* NOTE: The VBR value should be at P1 - (or P2, virtural "fixed" address space). - It's definitely should not in physical address. */ - - asm volatile("ldc %0, vbr" - : /* no output */ - : "r" (&vbr_base) - : "memory"); -} - -void *set_exception_table_vec(unsigned int vec, void *handler) -{ - extern void *exception_handling_table[]; - void *old_handler; - - old_handler = exception_handling_table[vec]; - exception_handling_table[vec] = handler; - return old_handler; -} - -extern asmlinkage void address_error_handler(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs); - -void __init trap_init(void) -{ - set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); - set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst); - -#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ - defined(CONFIG_SH_FPU_EMU) - /* - * For SH-4 lacking an FPU, treat floating point instructions as - * reserved. They'll be handled in the math-emu case, or faulted on - * otherwise. - */ - set_exception_table_evt(0x800, do_reserved_inst); - set_exception_table_evt(0x820, do_illegal_slot_inst); -#elif defined(CONFIG_SH_FPU) -#ifdef CONFIG_CPU_SUBTYPE_SHX3 - set_exception_table_evt(0xd80, do_fpu_state_restore); - set_exception_table_evt(0xda0, do_fpu_state_restore); -#else - set_exception_table_evt(0x800, do_fpu_state_restore); - set_exception_table_evt(0x820, do_fpu_state_restore); -#endif -#endif - -#ifdef CONFIG_CPU_SH2 - set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_handler); -#endif -#ifdef CONFIG_CPU_SH2A - set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); - set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); -#endif - - /* Setup VBR for boot cpu */ - per_cpu_trap_init(); -} #ifdef CONFIG_BUG -void handle_BUG(struct pt_regs *regs) -{ - enum bug_trap_type tt; - tt = report_bug(regs->pc, regs); - if (tt == BUG_TRAP_TYPE_WARN) { - regs->pc += 2; - return; + if (__kernel_text_address(instruction_pointer(regs))) { + opcode_t insn = *(opcode_t *)instruction_pointer(regs); + if (insn == TRAPA_BUG_OPCODE) + handle_BUG(regs); } - - die("Kernel BUG", regs, TRAPA_BUG_OPCODE & 0xff); -} - -int is_valid_bugaddr(unsigned long addr) -{ - return addr >= PAGE_OFFSET; -} #endif -void show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs) -{ - unsigned long addr; - - if (regs && user_mode(regs)) - return; - - printk("\nCall trace: "); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - - while (!kstack_end(sp)) { - addr = *sp++; - if (kernel_text_address(addr)) - print_ip_sym(addr); - } - - printk("\n"); - - if (!tsk) - tsk = current; - - debug_show_held_locks(tsk); -} - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ - unsigned long stack; - - if (!tsk) - tsk = current; - if (tsk == current) - sp = (unsigned long *)current_stack_pointer; - else - sp = (unsigned long *)tsk->thread.sp; - - stack = (unsigned long)sp; - dump_mem("Stack: ", stack, THREAD_SIZE + - (unsigned long)task_stack_page(tsk)); - show_trace(tsk, sp, NULL); -} - -void dump_stack(void) -{ - show_stack(NULL, NULL); + force_sig(SIGTRAP, current); } -EXPORT_SYMBOL(dump_stack); diff -puN /dev/null arch/sh/kernel/traps_32.c --- /dev/null +++ a/arch/sh/kernel/traps_32.c @@ -0,0 +1,919 @@ +/* + * 'traps.c' handles hardware traps and faults after we have saved some + * state in 'entry.S'. + * + * SuperH version: Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2000 Philipp Rumpf + * Copyright (C) 2000 David Howells + * Copyright (C) 2002 - 2007 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_SH_KGDB +#include +#define CHK_REMOTE_DEBUG(regs) \ +{ \ + if (kgdb_debug_hook && !user_mode(regs))\ + (*kgdb_debug_hook)(regs); \ +} +#else +#define CHK_REMOTE_DEBUG(regs) +#endif + +#ifdef CONFIG_CPU_SH2 +# define TRAP_RESERVED_INST 4 +# define TRAP_ILLEGAL_SLOT_INST 6 +# define TRAP_ADDRESS_ERROR 9 +# ifdef CONFIG_CPU_SH2A +# define TRAP_DIVZERO_ERROR 17 +# define TRAP_DIVOVF_ERROR 18 +# endif +#else +#define TRAP_RESERVED_INST 12 +#define TRAP_ILLEGAL_SLOT_INST 13 +#endif + +static void dump_mem(const char *str, unsigned long bottom, unsigned long top) +{ + unsigned long p; + int i; + + printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top); + + for (p = bottom & ~31; p < top; ) { + printk("%04lx: ", p & 0xffff); + + for (i = 0; i < 8; i++, p += 4) { + unsigned int val; + + if (p < bottom || p >= top) + printk(" "); + else { + if (__get_user(val, (unsigned int __user *)p)) { + printk("\n"); + return; + } + printk("%08x ", val); + } + } + printk("\n"); + } +} + +static DEFINE_SPINLOCK(die_lock); + +void die(const char * str, struct pt_regs * regs, long err) +{ + static int die_counter; + + oops_enter(); + + console_verbose(); + spin_lock_irq(&die_lock); + bust_spinlocks(1); + + printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); + + CHK_REMOTE_DEBUG(regs); + print_modules(); + show_regs(regs); + + printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm, + task_pid_nr(current), task_stack_page(current) + 1); + + if (!user_mode(regs) || in_interrupt()) + dump_mem("Stack: ", regs->regs[15], THREAD_SIZE + + (unsigned long)task_stack_page(current)); + + bust_spinlocks(0); + add_taint(TAINT_DIE); + spin_unlock_irq(&die_lock); + + if (kexec_should_crash(current)) + crash_kexec(regs); + + if (in_interrupt()) + panic("Fatal exception in interrupt"); + + if (panic_on_oops) + panic("Fatal exception"); + + oops_exit(); + do_exit(SIGSEGV); +} + +static inline void die_if_kernel(const char *str, struct pt_regs *regs, + long err) +{ + if (!user_mode(regs)) + die(str, regs, err); +} + +/* + * try and fix up kernelspace address errors + * - userspace errors just cause EFAULT to be returned, resulting in SEGV + * - kernel/userspace interfaces cause a jump to an appropriate handler + * - other kernel errors are bad + * - return 0 if fixed-up, -EFAULT if non-fatal (to the kernel) fault + */ +static int die_if_no_fixup(const char * str, struct pt_regs * regs, long err) +{ + if (!user_mode(regs)) { + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return 0; + } + die(str, regs, err); + } + return -EFAULT; +} + +/* + * handle an instruction that does an unaligned memory access by emulating the + * desired behaviour + * - note that PC _may not_ point to the faulting instruction + * (if that instruction is in a branch delay slot) + * - return 0 if emulation okay, -EFAULT on existential error + */ +static int handle_unaligned_ins(u16 instruction, struct pt_regs *regs) +{ + int ret, index, count; + unsigned long *rm, *rn; + unsigned char *src, *dst; + + index = (instruction>>8)&15; /* 0x0F00 */ + rn = ®s->regs[index]; + + index = (instruction>>4)&15; /* 0x00F0 */ + rm = ®s->regs[index]; + + count = 1<<(instruction&3); + + ret = -EFAULT; + switch (instruction>>12) { + case 0: /* mov.[bwl] to/from memory via r0+rn */ + if (instruction & 8) { + /* from memory */ + src = (unsigned char*) *rm; + src += regs->regs[0]; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + +#ifdef __LITTLE_ENDIAN__ + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + dst += 4-count; + + if (__copy_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + } else { + /* to memory */ + src = (unsigned char*) rm; +#if !defined(__LITTLE_ENDIAN__) + src += 4-count; +#endif + dst = (unsigned char*) *rn; + dst += regs->regs[0]; + + if (copy_to_user(dst, src, count)) + goto fetch_fault; + } + ret = 0; + break; + + case 1: /* mov.l Rm,@(disp,Rn) */ + src = (unsigned char*) rm; + dst = (unsigned char*) *rn; + dst += (instruction&0x000F)<<2; + + if (copy_to_user(dst,src,4)) + goto fetch_fault; + ret = 0; + break; + + case 2: /* mov.[bwl] to memory, possibly with pre-decrement */ + if (instruction & 4) + *rn -= count; + src = (unsigned char*) rm; + dst = (unsigned char*) *rn; +#if !defined(__LITTLE_ENDIAN__) + src += 4-count; +#endif + if (copy_to_user(dst, src, count)) + goto fetch_fault; + ret = 0; + break; + + case 5: /* mov.l @(disp,Rm),Rn */ + src = (unsigned char*) *rm; + src += (instruction&0x000F)<<2; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + + if (copy_from_user(dst,src,4)) + goto fetch_fault; + ret = 0; + break; + + case 6: /* mov.[bwl] from memory, possibly with post-increment */ + src = (unsigned char*) *rm; + if (instruction & 4) + *rm += count; + dst = (unsigned char*) rn; + *(unsigned long*)dst = 0; + +#ifdef __LITTLE_ENDIAN__ + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + dst += 4-count; + + if (copy_from_user(dst, src, count)) + goto fetch_fault; + + if ((count == 2) && dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + ret = 0; + break; + + case 8: + switch ((instruction&0xFF00)>>8) { + case 0x81: /* mov.w R0,@(disp,Rn) */ + src = (unsigned char*) ®s->regs[0]; +#if !defined(__LITTLE_ENDIAN__) + src += 2; +#endif + dst = (unsigned char*) *rm; /* called Rn in the spec */ + dst += (instruction&0x000F)<<1; + + if (copy_to_user(dst, src, 2)) + goto fetch_fault; + ret = 0; + break; + + case 0x85: /* mov.w @(disp,Rm),R0 */ + src = (unsigned char*) *rm; + src += (instruction&0x000F)<<1; + dst = (unsigned char*) ®s->regs[0]; + *(unsigned long*)dst = 0; + +#if !defined(__LITTLE_ENDIAN__) + dst += 2; +#endif + + if (copy_from_user(dst, src, 2)) + goto fetch_fault; + +#ifdef __LITTLE_ENDIAN__ + if (dst[1] & 0x80) { + dst[2] = 0xff; + dst[3] = 0xff; + } +#else + if (dst[2] & 0x80) { + dst[0] = 0xff; + dst[1] = 0xff; + } +#endif + ret = 0; + break; + } + break; + } + return ret; + + fetch_fault: + /* Argh. Address not only misaligned but also non-existent. + * Raise an EFAULT and see if it's trapped + */ + return die_if_no_fixup("Fault in unaligned fixup", regs, 0); +} + +/* + * emulate the instruction in the delay slot + * - fetches the instruction from PC+2 + */ +static inline int handle_unaligned_delayslot(struct pt_regs *regs) +{ + u16 instruction; + + if (copy_from_user(&instruction, (u16 *)(regs->pc+2), 2)) { + /* the instruction-fetch faulted */ + if (user_mode(regs)) + return -EFAULT; + + /* kernel */ + die("delay-slot-insn faulting in handle_unaligned_delayslot", + regs, 0); + } + + return handle_unaligned_ins(instruction,regs); +} + +/* + * handle an instruction that does an unaligned memory access + * - have to be careful of branch delay-slot instructions that fault + * SH3: + * - if the branch would be taken PC points to the branch + * - if the branch would not be taken, PC points to delay-slot + * SH4: + * - PC always points to delayed branch + * - return 0 if handled, -EFAULT if failed (may not return if in kernel) + */ + +/* Macros to determine offset from current PC for branch instructions */ +/* Explicit type coercion is used to force sign extension where needed */ +#define SH_PC_8BIT_OFFSET(instr) ((((signed char)(instr))*2) + 4) +#define SH_PC_12BIT_OFFSET(instr) ((((signed short)(instr<<4))>>3) + 4) + +/* + * XXX: SH-2A needs this too, but it needs an overhaul thanks to mixed 32-bit + * opcodes.. + */ +#ifndef CONFIG_CPU_SH2A +static int handle_unaligned_notify_count = 10; + +static int handle_unaligned_access(u16 instruction, struct pt_regs *regs) +{ + u_int rm; + int ret, index; + + index = (instruction>>8)&15; /* 0x0F00 */ + rm = regs->regs[index]; + + /* shout about the first ten userspace fixups */ + if (user_mode(regs) && handle_unaligned_notify_count>0) { + handle_unaligned_notify_count--; + + printk(KERN_NOTICE "Fixing up unaligned userspace access " + "in \"%s\" pid=%d pc=0x%p ins=0x%04hx\n", + current->comm, task_pid_nr(current), + (u16 *)regs->pc, instruction); + } + + ret = -EFAULT; + switch (instruction&0xF000) { + case 0x0000: + if (instruction==0x000B) { + /* rts */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc = regs->pr; + } + else if ((instruction&0x00FF)==0x0023) { + /* braf @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += rm + 4; + } + else if ((instruction&0x00FF)==0x0003) { + /* bsrf @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc += rm + 4; + } + } + else { + /* mov.[bwl] to/from memory via r0+rn */ + goto simple; + } + break; + + case 0x1000: /* mov.l Rm,@(disp,Rn) */ + goto simple; + + case 0x2000: /* mov.[bwl] to memory, possibly with pre-decrement */ + goto simple; + + case 0x4000: + if ((instruction&0x00FF)==0x002B) { + /* jmp @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc = rm; + } + else if ((instruction&0x00FF)==0x000B) { + /* jsr @Rm */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc = rm; + } + } + else { + /* mov.[bwl] to/from memory via r0+rn */ + goto simple; + } + break; + + case 0x5000: /* mov.l @(disp,Rm),Rn */ + goto simple; + + case 0x6000: /* mov.[bwl] from memory, possibly with post-increment */ + goto simple; + + case 0x8000: /* bf lab, bf/s lab, bt lab, bt/s lab */ + switch (instruction&0x0F00) { + case 0x0100: /* mov.w R0,@(disp,Rm) */ + goto simple; + case 0x0500: /* mov.w @(disp,Rm),R0 */ + goto simple; + case 0x0B00: /* bf lab - no delayslot*/ + break; + case 0x0F00: /* bf/s lab */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) + if ((regs->sr & 0x00000001) != 0) + regs->pc += 4; /* next after slot */ + else +#endif + regs->pc += SH_PC_8BIT_OFFSET(instruction); + } + break; + case 0x0900: /* bt lab - no delayslot */ + break; + case 0x0D00: /* bt/s lab */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { +#if defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB) + if ((regs->sr & 0x00000001) == 0) + regs->pc += 4; /* next after slot */ + else +#endif + regs->pc += SH_PC_8BIT_OFFSET(instruction); + } + break; + } + break; + + case 0xA000: /* bra label */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) + regs->pc += SH_PC_12BIT_OFFSET(instruction); + break; + + case 0xB000: /* bsr label */ + ret = handle_unaligned_delayslot(regs); + if (ret==0) { + regs->pr = regs->pc + 4; + regs->pc += SH_PC_12BIT_OFFSET(instruction); + } + break; + } + return ret; + + /* handle non-delay-slot instruction */ + simple: + ret = handle_unaligned_ins(instruction,regs); + if (ret==0) + regs->pc += instruction_size(instruction); + return ret; +} +#endif /* CONFIG_CPU_SH2A */ + +#ifdef CONFIG_CPU_HAS_SR_RB +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("stc r2_bank, %0\n\t" : "=r" ((x))) +#else +#define lookup_exception_vector(x) \ + __asm__ __volatile__ ("mov r4, %0\n\t" : "=r" ((x))) +#endif + +/* + * Handle various address error exceptions: + * - instruction address error: + * misaligned PC + * PC >= 0x80000000 in user mode + * - data address error (read and write) + * misaligned data access + * access to >= 0x80000000 is user mode + * Unfortuntaly we can't distinguish between instruction address error + * and data address errors caused by read accesses. + */ +asmlinkage void do_address_error(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) +{ + unsigned long error_code = 0; + mm_segment_t oldfs; + siginfo_t info; +#ifndef CONFIG_CPU_SH2A + u16 instruction; + int tmp; +#endif + + /* Intentional ifdef */ +#ifdef CONFIG_CPU_HAS_SR_RB + lookup_exception_vector(error_code); +#endif + + oldfs = get_fs(); + + if (user_mode(regs)) { + int si_code = BUS_ADRERR; + + local_irq_enable(); + + /* bad PC is not something we can fix */ + if (regs->pc & 1) { + si_code = BUS_ADRALN; + goto uspace_segv; + } + +#ifndef CONFIG_CPU_SH2A + set_fs(USER_DS); + if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { + /* Argh. Fault on the instruction itself. + This should never happen non-SMP + */ + set_fs(oldfs); + goto uspace_segv; + } + + tmp = handle_unaligned_access(instruction, regs); + set_fs(oldfs); + + if (tmp==0) + return; /* sorted */ +#endif + +uspace_segv: + printk(KERN_NOTICE "Sending SIGBUS to \"%s\" due to unaligned " + "access (PC %lx PR %lx)\n", current->comm, regs->pc, + regs->pr); + + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void __user *)address; + force_sig_info(SIGBUS, &info, current); + } else { + if (regs->pc & 1) + die("unaligned program counter", regs, error_code); + +#ifndef CONFIG_CPU_SH2A + set_fs(KERNEL_DS); + if (copy_from_user(&instruction, (u16 *)(regs->pc), 2)) { + /* Argh. Fault on the instruction itself. + This should never happen non-SMP + */ + set_fs(oldfs); + die("insn faulting in do_address_error", regs, 0); + } + + handle_unaligned_access(instruction, regs); + set_fs(oldfs); +#else + printk(KERN_NOTICE "Killing process \"%s\" due to unaligned " + "access\n", current->comm); + + force_sig(SIGSEGV, current); +#endif + } +} + +#ifdef CONFIG_SH_DSP +/* + * SH-DSP support gerg@snapgear.com. + */ +int is_dsp_inst(struct pt_regs *regs) +{ + unsigned short inst = 0; + + /* + * Safe guard if DSP mode is already enabled or we're lacking + * the DSP altogether. + */ + if (!(current_cpu_data.flags & CPU_HAS_DSP) || (regs->sr & SR_DSP)) + return 0; + + get_user(inst, ((unsigned short *) regs->pc)); + + inst &= 0xf000; + + /* Check for any type of DSP or support instruction */ + if ((inst == 0xf000) || (inst == 0x4000)) + return 1; + + return 0; +} +#else +#define is_dsp_inst(regs) (0) +#endif /* CONFIG_SH_DSP */ + +#ifdef CONFIG_CPU_SH2A +asmlinkage void do_divide_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + siginfo_t info; + + switch (r4) { + case TRAP_DIVZERO_ERROR: + info.si_code = FPE_INTDIV; + break; + case TRAP_DIVOVF_ERROR: + info.si_code = FPE_INTOVF; + break; + } + + force_sig_info(SIGFPE, &info, current); +} +#endif + +asmlinkage void do_reserved_inst(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + unsigned long error_code; + struct task_struct *tsk = current; + +#ifdef CONFIG_SH_FPU_EMU + unsigned short inst = 0; + int err; + + get_user(inst, (unsigned short*)regs->pc); + + err = do_fpu_inst(inst, regs); + if (!err) { + regs->pc += instruction_size(inst); + return; + } + /* not a FPU inst. */ +#endif + +#ifdef CONFIG_SH_DSP + /* Check if it's a DSP instruction */ + if (is_dsp_inst(regs)) { + /* Enable DSP mode, and restart instruction. */ + regs->sr |= SR_DSP; + return; + } +#endif + + lookup_exception_vector(error_code); + + local_irq_enable(); + CHK_REMOTE_DEBUG(regs); + force_sig(SIGILL, tsk); + die_if_no_fixup("reserved instruction", regs, error_code); +} + +#ifdef CONFIG_SH_FPU_EMU +static int emulate_branch(unsigned short inst, struct pt_regs* regs) +{ + /* + * bfs: 8fxx: PC+=d*2+4; + * bts: 8dxx: PC+=d*2+4; + * bra: axxx: PC+=D*2+4; + * bsr: bxxx: PC+=D*2+4 after PR=PC+4; + * braf:0x23: PC+=Rn*2+4; + * bsrf:0x03: PC+=Rn*2+4 after PR=PC+4; + * jmp: 4x2b: PC=Rn; + * jsr: 4x0b: PC=Rn after PR=PC+4; + * rts: 000b: PC=PR; + */ + if ((inst & 0xfd00) == 0x8d00) { + regs->pc += SH_PC_8BIT_OFFSET(inst); + return 0; + } + + if ((inst & 0xe000) == 0xa000) { + regs->pc += SH_PC_12BIT_OFFSET(inst); + return 0; + } + + if ((inst & 0xf0df) == 0x0003) { + regs->pc += regs->regs[(inst & 0x0f00) >> 8] + 4; + return 0; + } + + if ((inst & 0xf0df) == 0x400b) { + regs->pc = regs->regs[(inst & 0x0f00) >> 8]; + return 0; + } + + if ((inst & 0xffff) == 0x000b) { + regs->pc = regs->pr; + return 0; + } + + return 1; +} +#endif + +asmlinkage void do_illegal_slot_inst(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + unsigned long error_code; + struct task_struct *tsk = current; +#ifdef CONFIG_SH_FPU_EMU + unsigned short inst = 0; + + get_user(inst, (unsigned short *)regs->pc + 1); + if (!do_fpu_inst(inst, regs)) { + get_user(inst, (unsigned short *)regs->pc); + if (!emulate_branch(inst, regs)) + return; + /* fault in branch.*/ + } + /* not a FPU inst. */ +#endif + + lookup_exception_vector(error_code); + + local_irq_enable(); + CHK_REMOTE_DEBUG(regs); + force_sig(SIGILL, tsk); + die_if_no_fixup("illegal slot instruction", regs, error_code); +} + +asmlinkage void do_exception_error(unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7, + struct pt_regs __regs) +{ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); + long ex; + + lookup_exception_vector(ex); + die_if_kernel("exception", regs, ex); +} + +#if defined(CONFIG_SH_STANDARD_BIOS) +void *gdb_vbr_vector; + +static inline void __init gdb_vbr_init(void) +{ + register unsigned long vbr; + + /* + * Read the old value of the VBR register to initialise + * the vector through which debug and BIOS traps are + * delegated by the Linux trap handler. + */ + asm volatile("stc vbr, %0" : "=r" (vbr)); + + gdb_vbr_vector = (void *)(vbr + 0x100); + printk("Setting GDB trap vector to 0x%08lx\n", + (unsigned long)gdb_vbr_vector); +} +#endif + +void __cpuinit per_cpu_trap_init(void) +{ + extern void *vbr_base; + +#ifdef CONFIG_SH_STANDARD_BIOS + if (raw_smp_processor_id() == 0) + gdb_vbr_init(); +#endif + + /* NOTE: The VBR value should be at P1 + (or P2, virtural "fixed" address space). + It's definitely should not in physical address. */ + + asm volatile("ldc %0, vbr" + : /* no output */ + : "r" (&vbr_base) + : "memory"); +} + +void *set_exception_table_vec(unsigned int vec, void *handler) +{ + extern void *exception_handling_table[]; + void *old_handler; + + old_handler = exception_handling_table[vec]; + exception_handling_table[vec] = handler; + return old_handler; +} + +void __init trap_init(void) +{ + set_exception_table_vec(TRAP_RESERVED_INST, do_reserved_inst); + set_exception_table_vec(TRAP_ILLEGAL_SLOT_INST, do_illegal_slot_inst); + +#if defined(CONFIG_CPU_SH4) && !defined(CONFIG_SH_FPU) || \ + defined(CONFIG_SH_FPU_EMU) + /* + * For SH-4 lacking an FPU, treat floating point instructions as + * reserved. They'll be handled in the math-emu case, or faulted on + * otherwise. + */ + set_exception_table_evt(0x800, do_reserved_inst); + set_exception_table_evt(0x820, do_illegal_slot_inst); +#elif defined(CONFIG_SH_FPU) +#ifdef CONFIG_CPU_SUBTYPE_SHX3 + set_exception_table_evt(0xd80, fpu_state_restore_trap_handler); + set_exception_table_evt(0xda0, fpu_state_restore_trap_handler); +#else + set_exception_table_evt(0x800, fpu_state_restore_trap_handler); + set_exception_table_evt(0x820, fpu_state_restore_trap_handler); +#endif +#endif + +#ifdef CONFIG_CPU_SH2 + set_exception_table_vec(TRAP_ADDRESS_ERROR, address_error_trap_handler); +#endif +#ifdef CONFIG_CPU_SH2A + set_exception_table_vec(TRAP_DIVZERO_ERROR, do_divide_error); + set_exception_table_vec(TRAP_DIVOVF_ERROR, do_divide_error); +#endif + + /* Setup VBR for boot cpu */ + per_cpu_trap_init(); +} + +void show_trace(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs) +{ + unsigned long addr; + + if (regs && user_mode(regs)) + return; + + printk("\nCall trace: "); +#ifdef CONFIG_KALLSYMS + printk("\n"); +#endif + + while (!kstack_end(sp)) { + addr = *sp++; + if (kernel_text_address(addr)) + print_ip_sym(addr); + } + + printk("\n"); + + if (!tsk) + tsk = current; + + debug_show_held_locks(tsk); +} + +void show_stack(struct task_struct *tsk, unsigned long *sp) +{ + unsigned long stack; + + if (!tsk) + tsk = current; + if (tsk == current) + sp = (unsigned long *)current_stack_pointer; + else + sp = (unsigned long *)tsk->thread.sp; + + stack = (unsigned long)sp; + dump_mem("Stack: ", stack, THREAD_SIZE + + (unsigned long)task_stack_page(tsk)); + show_trace(tsk, sp, NULL); +} + +void dump_stack(void) +{ + show_stack(NULL, NULL); +} +EXPORT_SYMBOL(dump_stack); diff -puN /dev/null arch/sh/kernel/traps_64.c --- /dev/null +++ a/arch/sh/kernel/traps_64.c @@ -0,0 +1,975 @@ +/* + * arch/sh/kernel/traps_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2003, 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_EXCEPTION +#ifdef DEBUG_EXCEPTION +/* implemented in ../lib/dbg.c */ +extern void show_excp_regs(char *fname, int trapnr, int signr, + struct pt_regs *regs); +#else +#define show_excp_regs(a, b, c, d) +#endif + +static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, + unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk); + +#define DO_ERROR(trapnr, signr, str, name, tsk) \ +asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ +{ \ + do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \ +} + +spinlock_t die_lock; + +void die(const char * str, struct pt_regs * regs, long err) +{ + console_verbose(); + spin_lock_irq(&die_lock); + printk("%s: %lx\n", str, (err & 0xffffff)); + show_regs(regs); + spin_unlock_irq(&die_lock); + do_exit(SIGSEGV); +} + +static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) +{ + if (!user_mode(regs)) + die(str, regs, err); +} + +static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) +{ + if (!user_mode(regs)) { + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return; + } + die(str, regs, err); + } +} + +DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) +DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current) + + +/* Implement misaligned load/store handling for kernel (and optionally for user + mode too). Limitation : only SHmedia mode code is handled - there is no + handling at all for misaligned accesses occurring in SHcompact code yet. */ + +static int misaligned_fixup(struct pt_regs *regs); + +asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs) +{ + if (misaligned_fixup(regs) < 0) { + do_unhandled_exception(7, SIGSEGV, "address error(load)", + "do_address_error_load", + error_code, regs, current); + } + return; +} + +asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs) +{ + if (misaligned_fixup(regs) < 0) { + do_unhandled_exception(8, SIGSEGV, "address error(store)", + "do_address_error_store", + error_code, regs, current); + } + return; +} + +#if defined(CONFIG_SH64_ID2815_WORKAROUND) + +#define OPCODE_INVALID 0 +#define OPCODE_USER_VALID 1 +#define OPCODE_PRIV_VALID 2 + +/* getcon/putcon - requires checking which control register is referenced. */ +#define OPCODE_CTRL_REG 3 + +/* Table of valid opcodes for SHmedia mode. + Form a 10-bit value by concatenating the major/minor opcodes i.e. + opcode[31:26,20:16]. The 6 MSBs of this value index into the following + array. The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to + LSBs==4'b0000 etc). */ +static unsigned long shmedia_opcode_table[64] = { + 0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015, + 0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000, + 0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000, + 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, + 0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000 +}; + +void do_reserved_inst(unsigned long error_code, struct pt_regs *regs) +{ + /* Workaround SH5-101 cut2 silicon defect #2815 : + in some situations, inter-mode branches from SHcompact -> SHmedia + which should take ITLBMISS or EXECPROT exceptions at the target + falsely take RESINST at the target instead. */ + + unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */ + unsigned long pc, aligned_pc; + int get_user_error; + int trapnr = 12; + int signr = SIGILL; + char *exception_name = "reserved_instruction"; + + pc = regs->pc; + if ((pc & 3) == 1) { + /* SHmedia : check for defect. This requires executable vmas + to be readable too. */ + aligned_pc = pc & ~3; + if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { + get_user_error = -EFAULT; + } else { + get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); + } + if (get_user_error >= 0) { + unsigned long index, shift; + unsigned long major, minor, combined; + unsigned long reserved_field; + reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */ + major = (opcode >> 26) & 0x3f; + minor = (opcode >> 16) & 0xf; + combined = (major << 4) | minor; + index = major; + shift = minor << 1; + if (reserved_field == 0) { + int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3; + switch (opcode_state) { + case OPCODE_INVALID: + /* Trap. */ + break; + case OPCODE_USER_VALID: + /* Restart the instruction : the branch to the instruction will now be from an RTE + not from SHcompact so the silicon defect won't be triggered. */ + return; + case OPCODE_PRIV_VALID: + if (!user_mode(regs)) { + /* Should only ever get here if a module has + SHcompact code inside it. If so, the same fix up is needed. */ + return; /* same reason */ + } + /* Otherwise, user mode trying to execute a privileged instruction - + fall through to trap. */ + break; + case OPCODE_CTRL_REG: + /* If in privileged mode, return as above. */ + if (!user_mode(regs)) return; + /* In user mode ... */ + if (combined == 0x9f) { /* GETCON */ + unsigned long regno = (opcode >> 20) & 0x3f; + if (regno >= 62) { + return; + } + /* Otherwise, reserved or privileged control register, => trap */ + } else if (combined == 0x1bf) { /* PUTCON */ + unsigned long regno = (opcode >> 4) & 0x3f; + if (regno >= 62) { + return; + } + /* Otherwise, reserved or privileged control register, => trap */ + } else { + /* Trap */ + } + break; + default: + /* Fall through to trap. */ + break; + } + } + /* fall through to normal resinst processing */ + } else { + /* Error trying to read opcode. This typically means a + real fault, not a RESINST any more. So change the + codes. */ + trapnr = 87; + exception_name = "address error (exec)"; + signr = SIGSEGV; + } + } + + do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current); +} + +#else /* CONFIG_SH64_ID2815_WORKAROUND */ + +/* If the workaround isn't needed, this is just a straightforward reserved + instruction */ +DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) + +#endif /* CONFIG_SH64_ID2815_WORKAROUND */ + +/* Called with interrupts disabled */ +asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) +{ + show_excp_regs(__FUNCTION__, -1, -1, regs); + die_if_kernel("exception", regs, ex); +} + +int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) +{ + /* Syscall debug */ + printk("System call ID error: [0x1#args:8 #syscall:16 0x%lx]\n", scId); + + die_if_kernel("unknown trapa", regs, scId); + + return -ENOSYS; +} + +void show_stack(struct task_struct *tsk, unsigned long *sp) +{ +#ifdef CONFIG_KALLSYMS + extern void sh64_unwind(struct pt_regs *regs); + struct pt_regs *regs; + + regs = tsk ? tsk->thread.kregs : NULL; + + sh64_unwind(regs); +#else + printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n"); +#endif +} + +void show_task(unsigned long *sp) +{ + show_stack(NULL, sp); +} + +void dump_stack(void) +{ + show_task(NULL); +} +/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */ +EXPORT_SYMBOL(dump_stack); + +static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, + unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) +{ + show_excp_regs(fn_name, trapnr, signr, regs); + tsk->thread.error_code = error_code; + tsk->thread.trap_no = trapnr; + + if (user_mode(regs)) + force_sig(signr, tsk); + + die_if_no_fixup(str, regs, error_code); +} + +static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode) +{ + int get_user_error; + unsigned long aligned_pc; + unsigned long opcode; + + if ((pc & 3) == 1) { + /* SHmedia */ + aligned_pc = pc & ~3; + if (from_user_mode) { + if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { + get_user_error = -EFAULT; + } else { + get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); + *result_opcode = opcode; + } + return get_user_error; + } else { + /* If the fault was in the kernel, we can either read + * this directly, or if not, we fault. + */ + *result_opcode = *(unsigned long *) aligned_pc; + return 0; + } + } else if ((pc & 1) == 0) { + /* SHcompact */ + /* TODO : provide handling for this. We don't really support + user-mode SHcompact yet, and for a kernel fault, this would + have to come from a module built for SHcompact. */ + return -EFAULT; + } else { + /* misaligned */ + return -EFAULT; + } +} + +static int address_is_sign_extended(__u64 a) +{ + __u64 b; +#if (NEFF == 32) + b = (__u64)(__s64)(__s32)(a & 0xffffffffUL); + return (b == a) ? 1 : 0; +#else +#error "Sign extend check only works for NEFF==32" +#endif +} + +static int generate_and_check_address(struct pt_regs *regs, + __u32 opcode, + int displacement_not_indexed, + int width_shift, + __u64 *address) +{ + /* return -1 for fault, 0 for OK */ + + __u64 base_address, addr; + int basereg; + + basereg = (opcode >> 20) & 0x3f; + base_address = regs->regs[basereg]; + if (displacement_not_indexed) { + __s64 displacement; + displacement = (opcode >> 10) & 0x3ff; + displacement = ((displacement << 54) >> 54); /* sign extend */ + addr = (__u64)((__s64)base_address + (displacement << width_shift)); + } else { + __u64 offset; + int offsetreg; + offsetreg = (opcode >> 10) & 0x3f; + offset = regs->regs[offsetreg]; + addr = base_address + offset; + } + + /* Check sign extended */ + if (!address_is_sign_extended(addr)) { + return -1; + } + +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + /* Check accessible. For misaligned access in the kernel, assume the + address is always accessible (and if not, just fault when the + load/store gets done.) */ + if (user_mode(regs)) { + if (addr >= TASK_SIZE) { + return -1; + } + /* Do access_ok check later - it depends on whether it's a load or a store. */ + } +#endif + + *address = addr; + return 0; +} + +/* Default value as for sh */ +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) +static int user_mode_unaligned_fixup_count = 10; +static int user_mode_unaligned_fixup_enable = 1; +#endif + +static int kernel_mode_unaligned_fixup_count = 32; + +static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result) +{ + unsigned short x; + unsigned char *p, *q; + p = (unsigned char *) (int) address; + q = (unsigned char *) &x; + q[0] = p[0]; + q[1] = p[1]; + + if (do_sign_extend) { + *result = (__u64)(__s64) *(short *) &x; + } else { + *result = (__u64) x; + } +} + +static void misaligned_kernel_word_store(__u64 address, __u64 value) +{ + unsigned short x; + unsigned char *p, *q; + p = (unsigned char *) (int) address; + q = (unsigned char *) &x; + + x = (__u16) value; + p[0] = q[0]; + p[1] = q[1]; +} + +static int misaligned_load(struct pt_regs *regs, + __u32 opcode, + int displacement_not_indexed, + int width_shift, + int do_sign_extend) +{ + /* Return -1 for a fault, 0 for OK */ + int error; + int destreg; + __u64 address; + + error = generate_and_check_address(regs, opcode, + displacement_not_indexed, width_shift, &address); + if (error < 0) { + return error; + } + + destreg = (opcode >> 4) & 0x3f; +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + if (user_mode(regs)) { + __u64 buffer; + + if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL< 0) { + return -1; /* fault */ + } + switch (width_shift) { + case 1: + if (do_sign_extend) { + regs->regs[destreg] = (__u64)(__s64) *(__s16 *) &buffer; + } else { + regs->regs[destreg] = (__u64) *(__u16 *) &buffer; + } + break; + case 2: + regs->regs[destreg] = (__u64)(__s64) *(__s32 *) &buffer; + break; + case 3: + regs->regs[destreg] = buffer; + break; + default: + printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + } else +#endif + { + /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ + __u64 lo, hi; + + switch (width_shift) { + case 1: + misaligned_kernel_word_load(address, do_sign_extend, ®s->regs[destreg]); + break; + case 2: + asm ("ldlo.l %1, 0, %0" : "=r" (lo) : "r" (address)); + asm ("ldhi.l %1, 3, %0" : "=r" (hi) : "r" (address)); + regs->regs[destreg] = lo | hi; + break; + case 3: + asm ("ldlo.q %1, 0, %0" : "=r" (lo) : "r" (address)); + asm ("ldhi.q %1, 7, %0" : "=r" (hi) : "r" (address)); + regs->regs[destreg] = lo | hi; + break; + + default: + printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + } + + return 0; + +} + +static int misaligned_store(struct pt_regs *regs, + __u32 opcode, + int displacement_not_indexed, + int width_shift) +{ + /* Return -1 for a fault, 0 for OK */ + int error; + int srcreg; + __u64 address; + + error = generate_and_check_address(regs, opcode, + displacement_not_indexed, width_shift, &address); + if (error < 0) { + return error; + } + + srcreg = (opcode >> 4) & 0x3f; +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + if (user_mode(regs)) { + __u64 buffer; + + if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<regs[srcreg]; + break; + case 2: + *(__u32 *) &buffer = (__u32) regs->regs[srcreg]; + break; + case 3: + buffer = regs->regs[srcreg]; + break; + default: + printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + + if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { + return -1; /* fault */ + } + } else +#endif + { + /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ + __u64 val = regs->regs[srcreg]; + + switch (width_shift) { + case 1: + misaligned_kernel_word_store(address, val); + break; + case 2: + asm ("stlo.l %1, 0, %0" : : "r" (val), "r" (address)); + asm ("sthi.l %1, 3, %0" : : "r" (val), "r" (address)); + break; + case 3: + asm ("stlo.q %1, 0, %0" : : "r" (val), "r" (address)); + asm ("sthi.q %1, 7, %0" : : "r" (val), "r" (address)); + break; + + default: + printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + } + + return 0; + +} + +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) +/* Never need to fix up misaligned FPU accesses within the kernel since that's a real + error. */ +static int misaligned_fpu_load(struct pt_regs *regs, + __u32 opcode, + int displacement_not_indexed, + int width_shift, + int do_paired_load) +{ + /* Return -1 for a fault, 0 for OK */ + int error; + int destreg; + __u64 address; + + error = generate_and_check_address(regs, opcode, + displacement_not_indexed, width_shift, &address); + if (error < 0) { + return error; + } + + destreg = (opcode >> 4) & 0x3f; + if (user_mode(regs)) { + __u64 buffer; + __u32 buflo, bufhi; + + if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL< 0) { + return -1; /* fault */ + } + /* 'current' may be the current owner of the FPU state, so + context switch the registers into memory so they can be + indexed by register number. */ + if (last_task_used_math == current) { + enable_fpu(); + save_fpu(current, regs); + disable_fpu(); + last_task_used_math = NULL; + regs->sr |= SR_FD; + } + + buflo = *(__u32*) &buffer; + bufhi = *(1 + (__u32*) &buffer); + + switch (width_shift) { + case 2: + current->thread.fpu.hard.fp_regs[destreg] = buflo; + break; + case 3: + if (do_paired_load) { + current->thread.fpu.hard.fp_regs[destreg] = buflo; + current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; + } else { +#if defined(CONFIG_LITTLE_ENDIAN) + current->thread.fpu.hard.fp_regs[destreg] = bufhi; + current->thread.fpu.hard.fp_regs[destreg+1] = buflo; +#else + current->thread.fpu.hard.fp_regs[destreg] = buflo; + current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; +#endif + } + break; + default: + printk("Unexpected width_shift %d in misaligned_fpu_load, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + return 0; + } else { + die ("Misaligned FPU load inside kernel", regs, 0); + return -1; + } + + +} + +static int misaligned_fpu_store(struct pt_regs *regs, + __u32 opcode, + int displacement_not_indexed, + int width_shift, + int do_paired_load) +{ + /* Return -1 for a fault, 0 for OK */ + int error; + int srcreg; + __u64 address; + + error = generate_and_check_address(regs, opcode, + displacement_not_indexed, width_shift, &address); + if (error < 0) { + return error; + } + + srcreg = (opcode >> 4) & 0x3f; + if (user_mode(regs)) { + __u64 buffer; + /* Initialise these to NaNs. */ + __u32 buflo=0xffffffffUL, bufhi=0xffffffffUL; + + if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<sr |= SR_FD; + } + + switch (width_shift) { + case 2: + buflo = current->thread.fpu.hard.fp_regs[srcreg]; + break; + case 3: + if (do_paired_load) { + buflo = current->thread.fpu.hard.fp_regs[srcreg]; + bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; + } else { +#if defined(CONFIG_LITTLE_ENDIAN) + bufhi = current->thread.fpu.hard.fp_regs[srcreg]; + buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; +#else + buflo = current->thread.fpu.hard.fp_regs[srcreg]; + bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; +#endif + } + break; + default: + printk("Unexpected width_shift %d in misaligned_fpu_store, PC=%08lx\n", + width_shift, (unsigned long) regs->pc); + break; + } + + *(__u32*) &buffer = buflo; + *(1 + (__u32*) &buffer) = bufhi; + if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { + return -1; /* fault */ + } + return 0; + } else { + die ("Misaligned FPU load inside kernel", regs, 0); + return -1; + } +} +#endif + +static int misaligned_fixup(struct pt_regs *regs) +{ + unsigned long opcode; + int error; + int major, minor; + +#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + /* Never fixup user mode misaligned accesses without this option enabled. */ + return -1; +#else + if (!user_mode_unaligned_fixup_enable) return -1; +#endif + + error = read_opcode(regs->pc, &opcode, user_mode(regs)); + if (error < 0) { + return error; + } + major = (opcode >> 26) & 0x3f; + minor = (opcode >> 16) & 0xf; + +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) { + --user_mode_unaligned_fixup_count; + /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */ + printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", + current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); + } else +#endif + if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) { + --kernel_mode_unaligned_fixup_count; + if (in_interrupt()) { + printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n", + (__u32)regs->pc, opcode); + } else { + printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", + current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); + } + } + + + switch (major) { + case (0x84>>2): /* LD.W */ + error = misaligned_load(regs, opcode, 1, 1, 1); + break; + case (0xb0>>2): /* LD.UW */ + error = misaligned_load(regs, opcode, 1, 1, 0); + break; + case (0x88>>2): /* LD.L */ + error = misaligned_load(regs, opcode, 1, 2, 1); + break; + case (0x8c>>2): /* LD.Q */ + error = misaligned_load(regs, opcode, 1, 3, 0); + break; + + case (0xa4>>2): /* ST.W */ + error = misaligned_store(regs, opcode, 1, 1); + break; + case (0xa8>>2): /* ST.L */ + error = misaligned_store(regs, opcode, 1, 2); + break; + case (0xac>>2): /* ST.Q */ + error = misaligned_store(regs, opcode, 1, 3); + break; + + case (0x40>>2): /* indexed loads */ + switch (minor) { + case 0x1: /* LDX.W */ + error = misaligned_load(regs, opcode, 0, 1, 1); + break; + case 0x5: /* LDX.UW */ + error = misaligned_load(regs, opcode, 0, 1, 0); + break; + case 0x2: /* LDX.L */ + error = misaligned_load(regs, opcode, 0, 2, 1); + break; + case 0x3: /* LDX.Q */ + error = misaligned_load(regs, opcode, 0, 3, 0); + break; + default: + error = -1; + break; + } + break; + + case (0x60>>2): /* indexed stores */ + switch (minor) { + case 0x1: /* STX.W */ + error = misaligned_store(regs, opcode, 0, 1); + break; + case 0x2: /* STX.L */ + error = misaligned_store(regs, opcode, 0, 2); + break; + case 0x3: /* STX.Q */ + error = misaligned_store(regs, opcode, 0, 3); + break; + default: + error = -1; + break; + } + break; + +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + case (0x94>>2): /* FLD.S */ + error = misaligned_fpu_load(regs, opcode, 1, 2, 0); + break; + case (0x98>>2): /* FLD.P */ + error = misaligned_fpu_load(regs, opcode, 1, 3, 1); + break; + case (0x9c>>2): /* FLD.D */ + error = misaligned_fpu_load(regs, opcode, 1, 3, 0); + break; + case (0x1c>>2): /* floating indexed loads */ + switch (minor) { + case 0x8: /* FLDX.S */ + error = misaligned_fpu_load(regs, opcode, 0, 2, 0); + break; + case 0xd: /* FLDX.P */ + error = misaligned_fpu_load(regs, opcode, 0, 3, 1); + break; + case 0x9: /* FLDX.D */ + error = misaligned_fpu_load(regs, opcode, 0, 3, 0); + break; + default: + error = -1; + break; + } + break; + case (0xb4>>2): /* FLD.S */ + error = misaligned_fpu_store(regs, opcode, 1, 2, 0); + break; + case (0xb8>>2): /* FLD.P */ + error = misaligned_fpu_store(regs, opcode, 1, 3, 1); + break; + case (0xbc>>2): /* FLD.D */ + error = misaligned_fpu_store(regs, opcode, 1, 3, 0); + break; + case (0x3c>>2): /* floating indexed stores */ + switch (minor) { + case 0x8: /* FSTX.S */ + error = misaligned_fpu_store(regs, opcode, 0, 2, 0); + break; + case 0xd: /* FSTX.P */ + error = misaligned_fpu_store(regs, opcode, 0, 3, 1); + break; + case 0x9: /* FSTX.D */ + error = misaligned_fpu_store(regs, opcode, 0, 3, 0); + break; + default: + error = -1; + break; + } + break; +#endif + + default: + /* Fault */ + error = -1; + break; + } + + if (error < 0) { + return error; + } else { + regs->pc += 4; /* Skip the instruction that's just been emulated */ + return 0; + } + +} + +static ctl_table unaligned_table[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "kernel_reports", + .data = &kernel_mode_unaligned_fixup_count, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, +#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) + { + .ctl_name = CTL_UNNUMBERED, + .procname = "user_reports", + .data = &user_mode_unaligned_fixup_count, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec + }, + { + .ctl_name = CTL_UNNUMBERED, + .procname = "user_enable", + .data = &user_mode_unaligned_fixup_enable, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = &proc_dointvec}, +#endif + {} +}; + +static ctl_table unaligned_root[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "unaligned_fixup", + .mode = 0555, + unaligned_table + }, + {} +}; + +static ctl_table sh64_root[] = { + { + .ctl_name = CTL_UNNUMBERED, + .procname = "sh64", + .mode = 0555, + .child = unaligned_root + }, + {} +}; +static struct ctl_table_header *sysctl_header; +static int __init init_sysctl(void) +{ + sysctl_header = register_sysctl_table(sh64_root); + return 0; +} + +__initcall(init_sysctl); + + +asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) +{ + u64 peek_real_address_q(u64 addr); + u64 poke_real_address_q(u64 addr, u64 val); + unsigned long long DM_EXP_CAUSE_PHY = 0x0c100010; + unsigned long long exp_cause; + /* It's not worth ioremapping the debug module registers for the amount + of access we make to them - just go direct to their physical + addresses. */ + exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY); + if (exp_cause & ~4) { + printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n", + (unsigned long)(exp_cause & 0xffffffff)); + } + show_state(); + /* Clear all DEBUGINT causes */ + poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); +} diff -puN arch/sh/kernel/vmlinux.lds.S~git-sh arch/sh/kernel/vmlinux.lds.S --- a/arch/sh/kernel/vmlinux.lds.S~git-sh +++ a/arch/sh/kernel/vmlinux.lds.S @@ -1,138 +1,5 @@ -/* - * ld script to make SuperH Linux kernel - * Written by Niibe Yutaka - */ -#include -#include -#include - -#ifdef CONFIG_CPU_LITTLE_ENDIAN -OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux") +#ifdef CONFIG_SUPERH32 +# include "vmlinux_32.lds.S" #else -OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux") +# include "vmlinux_64.lds.S" #endif -OUTPUT_ARCH(sh) -ENTRY(_start) -SECTIONS -{ - . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; - _text = .; /* Text and read-only data */ - - .empty_zero_page : { - *(.empty_zero_page) - } = 0 - - .text : { - *(.text.head) - TEXT_TEXT - SCHED_TEXT - LOCK_TEXT - KPROBES_TEXT - *(.fixup) - *(.gnu.warning) - } = 0x0009 - - . = ALIGN(16); /* Exception table */ - __start___ex_table = .; - __ex_table : { *(__ex_table) } - __stop___ex_table = .; - - _etext = .; /* End of text section */ - - BUG_TABLE - NOTES - RO_DATA(PAGE_SIZE) - - . = ALIGN(THREAD_SIZE); - .data : { /* Data */ - *(.data.init_task) - - . = ALIGN(L1_CACHE_BYTES); - *(.data.cacheline_aligned) - - . = ALIGN(L1_CACHE_BYTES); - *(.data.read_mostly) - - . = ALIGN(PAGE_SIZE); - *(.data.page_aligned) - - __nosave_begin = .; - *(.data.nosave) - . = ALIGN(PAGE_SIZE); - __nosave_end = .; - - DATA_DATA - CONSTRUCTORS - } - - _edata = .; /* End of data section */ - - . = ALIGN(PAGE_SIZE); /* Init code and data */ - __init_begin = .; - _sinittext = .; - .init.text : { *(.init.text) } - _einittext = .; - .init.data : { *(.init.data) } - - . = ALIGN(16); - __setup_start = .; - .init.setup : { *(.init.setup) } - __setup_end = .; - - __initcall_start = .; - .initcall.init : { - INITCALLS - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : { *(.con_initcall.init) } - __con_initcall_end = .; - - SECURITY_INIT - -#ifdef CONFIG_BLK_DEV_INITRD - . = ALIGN(PAGE_SIZE); - __initramfs_start = .; - .init.ramfs : { *(.init.ramfs) } - __initramfs_end = .; -#endif - - . = ALIGN(4); - __machvec_start = .; - .machvec.init : { *(.machvec.init) } - __machvec_end = .; - - PERCPU(PAGE_SIZE) - - /* - * .exit.text is discarded at runtime, not link time, to deal with - * references from __bug_table - */ - .exit.text : { *(.exit.text) } - .exit.data : { *(.exit.data) } - - . = ALIGN(PAGE_SIZE); - .bss : { - __init_end = .; - __bss_start = .; /* BSS */ - *(.bss.page_aligned) - *(.bss) - *(COMMON) - . = ALIGN(4); - _ebss = .; /* uClinux MTD sucks */ - _end = . ; - } - - /* - * When something in the kernel is NOT compiled as a module, the - * module cleanup code and data are put into these segments. Both - * can then be thrown away, as cleanup code is never called unless - * it's a module. - */ - /DISCARD/ : { - *(.exitcall.exit) - } - - STABS_DEBUG - DWARF_DEBUG -} diff -puN /dev/null arch/sh/kernel/vmlinux_32.lds.S --- /dev/null +++ a/arch/sh/kernel/vmlinux_32.lds.S @@ -0,0 +1,152 @@ +/* + * ld script to make SuperH Linux kernel + * Written by Niibe Yutaka + */ +#include +#include +#include + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +OUTPUT_FORMAT("elf32-sh-linux", "elf32-sh-linux", "elf32-sh-linux") +#else +OUTPUT_FORMAT("elf32-shbig-linux", "elf32-shbig-linux", "elf32-shbig-linux") +#endif +OUTPUT_ARCH(sh) +ENTRY(_start) +SECTIONS +{ +#ifdef CONFIG_32BIT + . = CONFIG_PAGE_OFFSET + CONFIG_ZERO_PAGE_OFFSET; +#else + . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + CONFIG_ZERO_PAGE_OFFSET; +#endif + + _text = .; /* Text and read-only data */ + + .empty_zero_page : { + *(.empty_zero_page) + } = 0 + + .text : { + *(.text.head) + TEXT_TEXT + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) + *(.gnu.warning) + } = 0x0009 + + . = ALIGN(16); /* Exception table */ + __start___ex_table = .; + __ex_table : { *(__ex_table) } + __stop___ex_table = .; + + _etext = .; /* End of text section */ + + BUG_TABLE + NOTES + RO_DATA(PAGE_SIZE) + + /* + * Code which must be executed uncached and the associated data + */ + . = ALIGN(PAGE_SIZE); + __uncached_start = .; + .uncached.text : { *(.uncached.text) } + .uncached.data : { *(.uncached.data) } + __uncached_end = .; + + . = ALIGN(THREAD_SIZE); + .data : { /* Data */ + *(.data.init_task) + + . = ALIGN(L1_CACHE_BYTES); + *(.data.cacheline_aligned) + + . = ALIGN(L1_CACHE_BYTES); + *(.data.read_mostly) + + . = ALIGN(PAGE_SIZE); + *(.data.page_aligned) + + __nosave_begin = .; + *(.data.nosave) + . = ALIGN(PAGE_SIZE); + __nosave_end = .; + + DATA_DATA + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(PAGE_SIZE); /* Init code and data */ + __init_begin = .; + _sinittext = .; + .init.text : { *(.init.text) } + _einittext = .; + .init.data : { *(.init.data) } + + . = ALIGN(16); + __setup_start = .; + .init.setup : { *(.init.setup) } + __setup_end = .; + + __initcall_start = .; + .initcall.init : { + INITCALLS + } + __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : { *(.con_initcall.init) } + __con_initcall_end = .; + + SECURITY_INIT + +#ifdef CONFIG_BLK_DEV_INITRD + . = ALIGN(PAGE_SIZE); + __initramfs_start = .; + .init.ramfs : { *(.init.ramfs) } + __initramfs_end = .; +#endif + + . = ALIGN(4); + __machvec_start = .; + .machvec.init : { *(.machvec.init) } + __machvec_end = .; + + PERCPU(PAGE_SIZE) + + /* + * .exit.text is discarded at runtime, not link time, to deal with + * references from __bug_table + */ + .exit.text : { *(.exit.text) } + .exit.data : { *(.exit.data) } + + . = ALIGN(PAGE_SIZE); + .bss : { + __init_end = .; + __bss_start = .; /* BSS */ + *(.bss.page_aligned) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; /* uClinux MTD sucks */ + _end = . ; + } + + /* + * When something in the kernel is NOT compiled as a module, the + * module cleanup code and data are put into these segments. Both + * can then be thrown away, as cleanup code is never called unless + * it's a module. + */ + /DISCARD/ : { + *(.exitcall.exit) + } + + STABS_DEBUG + DWARF_DEBUG +} diff -puN /dev/null arch/sh/kernel/vmlinux_64.lds.S --- /dev/null +++ a/arch/sh/kernel/vmlinux_64.lds.S @@ -0,0 +1,164 @@ +/* + * ld script to make SH64 Linux kernel + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * benedict.gaster@superh.com: 2nd May 2002 + * Add definition of empty_zero_page to be the first page of kernel image. + * + * benedict.gaster@superh.com: 3rd May 2002 + * Added support for ramdisk, removing statically linked romfs at the + * same time. + * + * lethal@linux-sh.org: 9th May 2003 + * Kill off GLOBAL_NAME() usage and other CDC-isms. + * + * lethal@linux-sh.org: 19th May 2003 + * Remove support for ancient toolchains. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +#define LOAD_OFFSET CONFIG_PAGE_OFFSET +#include + +OUTPUT_ARCH(sh:sh5) + +#define C_PHYS(x) AT (ADDR(x) - LOAD_OFFSET) + +ENTRY(__start) +SECTIONS +{ + . = CONFIG_PAGE_OFFSET + CONFIG_MEMORY_START + PAGE_SIZE; + _text = .; /* Text and read-only data */ + + .empty_zero_page : C_PHYS(.empty_zero_page) { + *(.empty_zero_page) + } = 0 + + .text : C_PHYS(.text) { + *(.text.head) + TEXT_TEXT + *(.text64) + *(.text..SHmedia32) + SCHED_TEXT + LOCK_TEXT + KPROBES_TEXT + *(.fixup) + *(.gnu.warning) +#ifdef CONFIG_LITTLE_ENDIAN + } = 0x6ff0fff0 +#else + } = 0xf0fff06f +#endif + + /* We likely want __ex_table to be Cache Line aligned */ + . = ALIGN(L1_CACHE_BYTES); /* Exception table */ + __start___ex_table = .; + __ex_table : C_PHYS(__ex_table) { *(__ex_table) } + __stop___ex_table = .; + + _etext = .; /* End of text section */ + + BUG_TABLE + NOTES + RO_DATA(PAGE_SIZE) + + . = ALIGN(THREAD_SIZE); + .data : C_PHYS(.data) { /* Data */ + *(.data.init_task) + + . = ALIGN(L1_CACHE_BYTES); + *(.data.cacheline_aligned) + + . = ALIGN(L1_CACHE_BYTES); + *(.data.read_mostly) + + . = ALIGN(PAGE_SIZE); + *(.data.page_aligned) + + __nosave_begin = .; + *(.data.nosave) + . = ALIGN(PAGE_SIZE); + __nosave_end = .; + + DATA_DATA + CONSTRUCTORS + } + + _edata = .; /* End of data section */ + + . = ALIGN(PAGE_SIZE); /* Init code and data */ + __init_begin = .; + _sinittext = .; + .init.text : C_PHYS(.init.text) { *(.init.text) } + _einittext = .; + .init.data : C_PHYS(.init.data) { *(.init.data) } + . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */ + __setup_start = .; + .init.setup : C_PHYS(.init.setup) { *(.init.setup) } + __setup_end = .; + __initcall_start = .; + .initcall.init : C_PHYS(.initcall.init) { + INITCALLS + } + __initcall_end = .; + __con_initcall_start = .; + .con_initcall.init : C_PHYS(.con_initcall.init) { + *(.con_initcall.init) + } + __con_initcall_end = .; + + SECURITY_INIT + +#ifdef CONFIG_BLK_DEV_INITRD + . = ALIGN(PAGE_SIZE); + __initramfs_start = .; + .init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) } + __initramfs_end = .; +#endif + + . = ALIGN(8); + __machvec_start = .; + .machvec.init : C_PHYS(.machvec.init) { *(.machvec.init) } + __machvec_end = .; + + PERCPU(PAGE_SIZE) + + /* + * .exit.text is discarded at runtime, not link time, to deal with + * references from __bug_table + */ + .exit.text : C_PHYS(.exit.text) { *(.exit.text) } + .exit.data : C_PHYS(.exit.data) { *(.exit.data) } + + . = ALIGN(PAGE_SIZE); + .bss : C_PHYS(.bss) { + __init_end = .; + __bss_start = .; /* BSS */ + *(.bss.page_aligned) + *(.bss) + *(COMMON) + . = ALIGN(4); + _ebss = .; /* uClinux MTD sucks */ + _end = . ; + } + + /* + * When something in the kernel is NOT compiled as a module, the + * module cleanup code and data are put into these segments. Both + * can then be thrown away, as cleanup code is never called unless + * it's a module. + */ + /DISCARD/ : { + *(.exitcall.exit) + } + + STABS_DEBUG + DWARF_DEBUG +} diff -puN arch/sh/lib/Makefile~git-sh arch/sh/lib/Makefile --- a/arch/sh/lib/Makefile~git-sh +++ a/arch/sh/lib/Makefile @@ -2,12 +2,13 @@ # Makefile for SuperH-specific library files.. # -lib-y = delay.o memset.o memmove.o memchr.o \ +lib-y = delay.o io.o memset.o memmove.o memchr.o \ checksum.o strlen.o div64.o div64-generic.o memcpy-y := memcpy.o memcpy-$(CONFIG_CPU_SH4) := memcpy-sh4.o -lib-y += $(memcpy-y) +lib-$(CONFIG_MMU) += copy_page.o clear_page.o +lib-y += $(memcpy-y) EXTRA_CFLAGS += -Werror diff -puN /dev/null arch/sh/lib/clear_page.S --- /dev/null +++ a/arch/sh/lib/clear_page.S @@ -0,0 +1,154 @@ +/* + * __clear_user_page, __clear_user, clear_page implementation of SuperH + * + * Copyright (C) 2001 Kaz Kojima + * Copyright (C) 2001, 2002 Niibe Yutaka + * Copyright (C) 2006 Paul Mundt + */ +#include +#include + +/* + * clear_page + * @to: P1 address + * + * void clear_page(void *to) + */ + +/* + * r0 --- scratch + * r4 --- to + * r5 --- to + PAGE_SIZE + */ +ENTRY(clear_page) + mov r4,r5 + mov.l .Llimit,r0 + add r0,r5 + mov #0,r0 + ! +1: +#if defined(CONFIG_CPU_SH3) + mov.l r0,@r4 +#elif defined(CONFIG_CPU_SH4) + movca.l r0,@r4 + mov r4,r1 +#endif + add #32,r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 + mov.l r0,@-r4 +#if defined(CONFIG_CPU_SH4) + ocbwb @r1 +#endif + cmp/eq r5,r4 + bf/s 1b + add #28,r4 + ! + rts + nop + + .balign 4 +.Llimit: .long (PAGE_SIZE-28) + +ENTRY(__clear_user) + ! + mov #0, r0 + mov #0xe0, r1 ! 0xffffffe0 + ! + ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ] + ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ] + ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ] + ! + ! Clear area 0 + mov r4, r2 + ! + tst r1, r5 ! length < 32 + bt .Larea2 ! skip to remainder + ! + add #31, r2 + and r1, r2 + cmp/eq r4, r2 + bt .Larea1 + mov r2, r3 + sub r4, r3 + mov r3, r7 + mov r4, r2 + ! +.L0: dt r3 +0: mov.b r0, @r2 + bf/s .L0 + add #1, r2 + ! + sub r7, r5 + mov r2, r4 +.Larea1: + mov r4, r3 + add r5, r3 + and r1, r3 + cmp/hi r2, r3 + bf .Larea2 + ! + ! Clear area 1 +#if defined(CONFIG_CPU_SH4) +1: movca.l r0, @r2 +#else +1: mov.l r0, @r2 +#endif + add #4, r2 +2: mov.l r0, @r2 + add #4, r2 +3: mov.l r0, @r2 + add #4, r2 +4: mov.l r0, @r2 + add #4, r2 +5: mov.l r0, @r2 + add #4, r2 +6: mov.l r0, @r2 + add #4, r2 +7: mov.l r0, @r2 + add #4, r2 +8: mov.l r0, @r2 + add #4, r2 + cmp/hi r2, r3 + bt/s 1b + nop + ! + ! Clear area 2 +.Larea2: + mov r4, r3 + add r5, r3 + cmp/hs r3, r2 + bt/s .Ldone + sub r2, r3 +.L2: dt r3 +9: mov.b r0, @r2 + bf/s .L2 + add #1, r2 + ! +.Ldone: rts + mov #0, r0 ! return 0 as normal return + + ! return the number of bytes remained +.Lbad_clear_user: + mov r4, r0 + add r5, r0 + rts + sub r2, r0 + +.section __ex_table,"a" + .align 2 + .long 0b, .Lbad_clear_user + .long 1b, .Lbad_clear_user + .long 2b, .Lbad_clear_user + .long 3b, .Lbad_clear_user + .long 4b, .Lbad_clear_user + .long 5b, .Lbad_clear_user + .long 6b, .Lbad_clear_user + .long 7b, .Lbad_clear_user + .long 8b, .Lbad_clear_user + .long 9b, .Lbad_clear_user +.previous diff -puN /dev/null arch/sh/lib/copy_page.S --- /dev/null +++ a/arch/sh/lib/copy_page.S @@ -0,0 +1,389 @@ +/* + * copy_page, __copy_user_page, __copy_user implementation of SuperH + * + * Copyright (C) 2001 Niibe Yutaka & Kaz Kojima + * Copyright (C) 2002 Toshinobu Sugioka + * Copyright (C) 2006 Paul Mundt + */ +#include +#include + +/* + * copy_page + * @to: P1 address + * @from: P1 address + * + * void copy_page(void *to, void *from) + */ + +/* + * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch + * r8 --- from + PAGE_SIZE + * r9 --- not used + * r10 --- to + * r11 --- from + */ +ENTRY(copy_page) + mov.l r8,@-r15 + mov.l r10,@-r15 + mov.l r11,@-r15 + mov r4,r10 + mov r5,r11 + mov r5,r8 + mov.l .Lpsz,r0 + add r0,r8 + ! +1: mov.l @r11+,r0 + mov.l @r11+,r1 + mov.l @r11+,r2 + mov.l @r11+,r3 + mov.l @r11+,r4 + mov.l @r11+,r5 + mov.l @r11+,r6 + mov.l @r11+,r7 +#if defined(CONFIG_CPU_SH3) + mov.l r0,@r10 +#elif defined(CONFIG_CPU_SH4) + movca.l r0,@r10 + mov r10,r0 +#endif + add #32,r10 + mov.l r7,@-r10 + mov.l r6,@-r10 + mov.l r5,@-r10 + mov.l r4,@-r10 + mov.l r3,@-r10 + mov.l r2,@-r10 + mov.l r1,@-r10 +#if defined(CONFIG_CPU_SH4) + ocbwb @r0 +#endif + cmp/eq r11,r8 + bf/s 1b + add #28,r10 + ! + mov.l @r15+,r11 + mov.l @r15+,r10 + mov.l @r15+,r8 + rts + nop + + .balign 4 +.Lpsz: .long PAGE_SIZE + +/* + * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); + * Return the number of bytes NOT copied + */ +#define EX(...) \ + 9999: __VA_ARGS__ ; \ + .section __ex_table, "a"; \ + .long 9999b, 6000f ; \ + .previous +ENTRY(__copy_user) + ! Check if small number of bytes + mov #11,r0 + mov r4,r3 + cmp/gt r0,r6 ! r6 (len) > r0 (11) + bf/s .L_cleanup_loop_no_pop + add r6,r3 ! last destination address + + ! Calculate bytes needed to align to src + mov.l r11,@-r15 + neg r5,r0 + mov.l r10,@-r15 + add #4,r0 + mov.l r9,@-r15 + and #3,r0 + mov.l r8,@-r15 + tst r0,r0 + bt 2f + +1: + ! Copy bytes to long word align src +EX( mov.b @r5+,r1 ) + dt r0 + add #-1,r6 +EX( mov.b r1,@r4 ) + bf/s 1b + add #1,r4 + + ! Jump to appropriate routine depending on dest +2: mov #3,r1 + mov r6, r2 + and r4,r1 + shlr2 r2 + shll2 r1 + mova .L_jump_tbl,r0 + mov.l @(r0,r1),r1 + jmp @r1 + nop + + .align 2 +.L_jump_tbl: + .long .L_dest00 + .long .L_dest01 + .long .L_dest10 + .long .L_dest11 + +/* + * Come here if there are less than 12 bytes to copy + * + * Keep the branch target close, so the bf/s callee doesn't overflow + * and result in a more expensive branch being inserted. This is the + * fast-path for small copies, the jump via the jump table will hit the + * default slow-path cleanup. -PFM. + */ +.L_cleanup_loop_no_pop: + tst r6,r6 ! Check explicitly for zero + bt 1f + +2: +EX( mov.b @r5+,r0 ) + dt r6 +EX( mov.b r0,@r4 ) + bf/s 2b + add #1,r4 + +1: mov #0,r0 ! normal return +5000: + +# Exception handler: +.section .fixup, "ax" +6000: + mov.l 8000f,r1 + mov r3,r0 + jmp @r1 + sub r4,r0 + .align 2 +8000: .long 5000b + +.previous + rts + nop + +! Destination = 00 + +.L_dest00: + ! Skip the large copy for small transfers + mov #(32+32-4), r0 + cmp/gt r6, r0 ! r0 (60) > r6 (len) + bt 1f + + ! Align dest to a 32 byte boundary + neg r4,r0 + add #0x20, r0 + and #0x1f, r0 + tst r0, r0 + bt 2f + + sub r0, r6 + shlr2 r0 +3: +EX( mov.l @r5+,r1 ) + dt r0 +EX( mov.l r1,@r4 ) + bf/s 3b + add #4,r4 + +2: +EX( mov.l @r5+,r0 ) +EX( mov.l @r5+,r1 ) +EX( mov.l @r5+,r2 ) +EX( mov.l @r5+,r7 ) +EX( mov.l @r5+,r8 ) +EX( mov.l @r5+,r9 ) +EX( mov.l @r5+,r10 ) +EX( mov.l @r5+,r11 ) +#ifdef CONFIG_CPU_SH4 +EX( movca.l r0,@r4 ) +#else +EX( mov.l r0,@r4 ) +#endif + add #-32, r6 +EX( mov.l r1,@(4,r4) ) + mov #32, r0 +EX( mov.l r2,@(8,r4) ) + cmp/gt r6, r0 ! r0 (32) > r6 (len) +EX( mov.l r7,@(12,r4) ) +EX( mov.l r8,@(16,r4) ) +EX( mov.l r9,@(20,r4) ) +EX( mov.l r10,@(24,r4) ) +EX( mov.l r11,@(28,r4) ) + bf/s 2b + add #32,r4 + +1: mov r6, r0 + shlr2 r0 + tst r0, r0 + bt .L_cleanup +1: +EX( mov.l @r5+,r1 ) + dt r0 +EX( mov.l r1,@r4 ) + bf/s 1b + add #4,r4 + + bra .L_cleanup + nop + +! Destination = 10 + +.L_dest10: + mov r2,r7 + shlr2 r7 + shlr r7 + tst r7,r7 + mov #7,r0 + bt/s 1f + and r0,r2 +2: + dt r7 +#ifdef CONFIG_CPU_LITTLE_ENDIAN +EX( mov.l @r5+,r0 ) +EX( mov.l @r5+,r1 ) +EX( mov.l @r5+,r8 ) +EX( mov.l @r5+,r9 ) +EX( mov.l @r5+,r10 ) +EX( mov.w r0,@r4 ) + add #2,r4 + xtrct r1,r0 + xtrct r8,r1 + xtrct r9,r8 + xtrct r10,r9 + +EX( mov.l r0,@r4 ) +EX( mov.l r1,@(4,r4) ) +EX( mov.l r8,@(8,r4) ) +EX( mov.l r9,@(12,r4) ) + +EX( mov.l @r5+,r1 ) +EX( mov.l @r5+,r8 ) +EX( mov.l @r5+,r0 ) + xtrct r1,r10 + xtrct r8,r1 + xtrct r0,r8 + shlr16 r0 +EX( mov.l r10,@(16,r4) ) +EX( mov.l r1,@(20,r4) ) +EX( mov.l r8,@(24,r4) ) +EX( mov.w r0,@(28,r4) ) + bf/s 2b + add #30,r4 +#else +EX( mov.l @(28,r5),r0 ) +EX( mov.l @(24,r5),r8 ) +EX( mov.l @(20,r5),r9 ) +EX( mov.l @(16,r5),r10 ) +EX( mov.w r0,@(30,r4) ) + add #-2,r4 + xtrct r8,r0 + xtrct r9,r8 + xtrct r10,r9 +EX( mov.l r0,@(28,r4) ) +EX( mov.l r8,@(24,r4) ) +EX( mov.l r9,@(20,r4) ) + +EX( mov.l @(12,r5),r0 ) +EX( mov.l @(8,r5),r8 ) + xtrct r0,r10 +EX( mov.l @(4,r5),r9 ) + mov.l r10,@(16,r4) +EX( mov.l @r5,r10 ) + xtrct r8,r0 + xtrct r9,r8 + xtrct r10,r9 +EX( mov.l r0,@(12,r4) ) +EX( mov.l r8,@(8,r4) ) + swap.w r10,r0 +EX( mov.l r9,@(4,r4) ) +EX( mov.w r0,@(2,r4) ) + + add #32,r5 + bf/s 2b + add #34,r4 +#endif + tst r2,r2 + bt .L_cleanup + +1: ! Read longword, write two words per iteration +EX( mov.l @r5+,r0 ) + dt r2 +#ifdef CONFIG_CPU_LITTLE_ENDIAN +EX( mov.w r0,@r4 ) + shlr16 r0 +EX( mov.w r0,@(2,r4) ) +#else +EX( mov.w r0,@(2,r4) ) + shlr16 r0 +EX( mov.w r0,@r4 ) +#endif + bf/s 1b + add #4,r4 + + bra .L_cleanup + nop + +! Destination = 01 or 11 + +.L_dest01: +.L_dest11: + ! Read longword, write byte, word, byte per iteration +EX( mov.l @r5+,r0 ) + dt r2 +#ifdef CONFIG_CPU_LITTLE_ENDIAN +EX( mov.b r0,@r4 ) + shlr8 r0 + add #1,r4 +EX( mov.w r0,@r4 ) + shlr16 r0 +EX( mov.b r0,@(2,r4) ) + bf/s .L_dest01 + add #3,r4 +#else +EX( mov.b r0,@(3,r4) ) + shlr8 r0 + swap.w r0,r7 +EX( mov.b r7,@r4 ) + add #1,r4 +EX( mov.w r0,@r4 ) + bf/s .L_dest01 + add #3,r4 +#endif + +! Cleanup last few bytes +.L_cleanup: + mov r6,r0 + and #3,r0 + tst r0,r0 + bt .L_exit + mov r0,r6 + +.L_cleanup_loop: +EX( mov.b @r5+,r0 ) + dt r6 +EX( mov.b r0,@r4 ) + bf/s .L_cleanup_loop + add #1,r4 + +.L_exit: + mov #0,r0 ! normal return + +5000: + +# Exception handler: +.section .fixup, "ax" +6000: + mov.l 8000f,r1 + mov r3,r0 + jmp @r1 + sub r4,r0 + .align 2 +8000: .long 5000b + +.previous + mov.l @r15+,r8 + mov.l @r15+,r9 + mov.l @r15+,r10 + rts + mov.l @r15+,r11 diff -puN /dev/null arch/sh/lib/io.c --- /dev/null +++ a/arch/sh/lib/io.c @@ -0,0 +1,82 @@ +/* + * arch/sh/lib/io.c - SH32 optimized I/O routines + * + * Copyright (C) 2000 Stuart Menefy + * Copyright (C) 2005 Paul Mundt + * + * Provide real functions which expand to whatever the header file defined. + * Also definitions of machine independent IO functions. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include + +void __raw_readsl(unsigned long addr, void *datap, int len) +{ + u32 *data; + + for (data = datap; (len != 0) && (((u32)data & 0x1f) != 0); len--) + *data++ = ctrl_inl(addr); + + if (likely(len >= (0x20 >> 2))) { + int tmp2, tmp3, tmp4, tmp5, tmp6; + + __asm__ __volatile__( + "1: \n\t" + "mov.l @%7, r0 \n\t" + "mov.l @%7, %2 \n\t" +#ifdef CONFIG_CPU_SH4 + "movca.l r0, @%0 \n\t" +#else + "mov.l r0, @%0 \n\t" +#endif + "mov.l @%7, %3 \n\t" + "mov.l @%7, %4 \n\t" + "mov.l @%7, %5 \n\t" + "mov.l @%7, %6 \n\t" + "mov.l @%7, r7 \n\t" + "mov.l @%7, r0 \n\t" + "mov.l %2, @(0x04,%0) \n\t" + "mov #0x20>>2, %2 \n\t" + "mov.l %3, @(0x08,%0) \n\t" + "sub %2, %1 \n\t" + "mov.l %4, @(0x0c,%0) \n\t" + "cmp/hi %1, %2 ! T if 32 > len \n\t" + "mov.l %5, @(0x10,%0) \n\t" + "mov.l %6, @(0x14,%0) \n\t" + "mov.l r7, @(0x18,%0) \n\t" + "mov.l r0, @(0x1c,%0) \n\t" + "bf.s 1b \n\t" + " add #0x20, %0 \n\t" + : "=&r" (data), "=&r" (len), + "=&r" (tmp2), "=&r" (tmp3), "=&r" (tmp4), + "=&r" (tmp5), "=&r" (tmp6) + : "r"(addr), "0" (data), "1" (len) + : "r0", "r7", "t", "memory"); + } + + for (; len != 0; len--) + *data++ = ctrl_inl(addr); +} +EXPORT_SYMBOL(__raw_readsl); + +void __raw_writesl(unsigned long addr, const void *data, int len) +{ + if (likely(len != 0)) { + int tmp1; + + __asm__ __volatile__ ( + "1: \n\t" + "mov.l @%0+, %1 \n\t" + "dt %3 \n\t" + "bf.s 1b \n\t" + " mov.l %1, @%4 \n\t" + : "=&r" (data), "=&r" (tmp1) + : "0" (data), "r" (len), "r"(addr) + : "t", "memory"); + } +} +EXPORT_SYMBOL(__raw_writesl); diff -puN /dev/null arch/sh/lib64/.gitignore --- /dev/null +++ a/arch/sh/lib64/.gitignore @@ -0,0 +1 @@ +syscalltab.h diff -puN /dev/null arch/sh/lib64/Makefile --- /dev/null +++ a/arch/sh/lib64/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the SH-5 specific library files.. +# +# Copyright (C) 2000, 2001 Paolo Alberelli +# Copyright (C) 2003 Paul Mundt +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# + +# Panic should really be compiled as PIC +lib-y := udelay.o c-checksum.o dbg.o panic.o memcpy.o copy_user_memcpy.o \ + copy_page.o clear_page.o + diff -puN /dev/null arch/sh/lib64/c-checksum.c --- /dev/null +++ a/arch/sh/lib64/c-checksum.c @@ -0,0 +1,214 @@ +/* + * arch/sh/lib64/c-checksum.c + * + * This file contains network checksum routines that are better done + * in an architecture-specific manner due to speed.. + */ +#include +#include +#include +#include +#include +#include + +static inline unsigned short from64to16(unsigned long long x) +{ + /* add up 32-bit words for 33 bits */ + x = (x & 0xffffffff) + (x >> 32); + /* add up 16-bit and 17-bit words for 17+c bits */ + x = (x & 0xffff) + (x >> 16); + /* add up 16-bit and 2-bit for 16+c bit */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static inline unsigned short foldto16(unsigned long x) +{ + /* add up 16-bit for 17 bits */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static inline unsigned short myfoldto16(unsigned long long x) +{ + /* Fold down to 32-bits so we don't loose in the typedef-less + network stack. */ + /* 64 to 33 */ + x = (x & 0xffffffff) + (x >> 32); + /* 33 to 32 */ + x = (x & 0xffffffff) + (x >> 32); + + /* add up 16-bit for 17 bits */ + x = (x & 0xffff) + (x >> 16); + /* add up carry.. */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +#define odd(x) ((x)&1) +#define U16(x) ntohs(x) + +static unsigned long do_csum(const unsigned char *buff, int len) +{ + int odd, count; + unsigned long result = 0; + + pr_debug("do_csum buff %p, len %d (0x%x)\n", buff, len, len); +#ifdef DEBUG + for (i = 0; i < len; i++) { + if ((i % 26) == 0) + printk("\n"); + printk("%02X ", buff[i]); + } +#endif + + if (len <= 0) + goto out; + + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff << 8; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + buff += 4; + count--; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += *buff; + result = foldto16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + + pr_debug("\nCHECKSUM is 0x%lx\n", result); + + out: + return result; +} + +/* computes the checksum of a memory block at buff, length len, + and adds in "sum" (32-bit) */ +__wsum csum_partial(const void *buff, int len, __wsum sum) +{ + unsigned long long result = do_csum(buff, len); + + /* add in old sum, and carry.. */ + result += (__force u32)sum; + /* 32+c bits -> 32 bits */ + result = (result & 0xffffffff) + (result >> 32); + + pr_debug("csum_partial, buff %p len %d sum 0x%x result=0x%016Lx\n", + buff, len, sum, result); + + return (__force __wsum)result; +} + +/* Copy while checksumming, otherwise like csum_partial. */ +__wsum +csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) +{ + sum = csum_partial(src, len, sum); + memcpy(dst, src, len); + + return sum; +} + +/* Copy from userspace and compute checksum. If we catch an exception + then zero the rest of the buffer. */ +__wsum +csum_partial_copy_from_user(const void __user *src, void *dst, int len, + __wsum sum, int *err_ptr) +{ + int missing; + + pr_debug + ("csum_partial_copy_from_user src %p, dest %p, len %d, sum %08x, err_ptr %p\n", + src, dst, len, sum, err_ptr); + missing = copy_from_user(dst, src, len); + pr_debug(" access_ok %d\n", __access_ok((unsigned long) src, len)); + pr_debug(" missing %d\n", missing); + if (missing) { + memset(dst + len - missing, 0, missing); + *err_ptr = -EFAULT; + } + + return csum_partial(dst, len, sum); +} + +/* Copy to userspace and compute checksum. */ +__wsum +csum_partial_copy_to_user(const unsigned char *src, unsigned char *dst, int len, + __wsum sum, int *err_ptr) +{ + sum = csum_partial(src, len, sum); + + if (copy_to_user(dst, src, len)) + *err_ptr = -EFAULT; + + return sum; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + */ +__sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + pr_debug("ip_fast_csum %p,%d\n", iph, ihl); + + return (__force __sum16)~do_csum(iph, ihl * 4); +} + +__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, __wsum sum) +{ + unsigned long long result; + + pr_debug("ntohs(0x%x)=0x%x\n", 0xdead, ntohs(0xdead)); + pr_debug("htons(0x%x)=0x%x\n", 0xdead, htons(0xdead)); + + result = (__force u64) saddr + (__force u64) daddr + + (__force u64) sum + ((len + proto) << 8); + + /* Fold down to 32-bits so we don't loose in the typedef-less + network stack. */ + /* 64 to 33 */ + result = (result & 0xffffffff) + (result >> 32); + /* 33 to 32 */ + result = (result & 0xffffffff) + (result >> 32); + + pr_debug("%s saddr %x daddr %x len %x proto %x sum %x result %08Lx\n", + __FUNCTION__, saddr, daddr, len, proto, sum, result); + + return (__wsum)result; +} +EXPORT_SYMBOL(csum_tcpudp_nofold); diff -puN /dev/null arch/sh/lib64/clear_page.S --- /dev/null +++ a/arch/sh/lib64/clear_page.S @@ -0,0 +1,54 @@ +/* + Copyright 2003 Richard Curnow, SuperH (UK) Ltd. + + This file is subject to the terms and conditions of the GNU General Public + License. See the file "COPYING" in the main directory of this archive + for more details. + + Tight version of memset for the case of just clearing a page. It turns out + that having the alloco's spaced out slightly due to the increment/branch + pair causes them to contend less for access to the cache. Similarly, + keeping the stores apart from the allocos causes less contention. => Do two + separate loops. Do multiple stores per loop to amortise the + increment/branch cost a little. + + Parameters: + r2 : source effective address (start of page) + + Always clears 4096 bytes. + + Note : alloco guarded by synco to avoid TAKum03020 erratum + +*/ + + .section .text..SHmedia32,"ax" + .little + + .balign 8 + .global clear_page +clear_page: + pta/l 1f, tr1 + pta/l 2f, tr2 + ptabs/l r18, tr0 + + movi 4096, r7 + add r2, r7, r7 + add r2, r63, r6 +1: + alloco r6, 0 + synco ! TAKum03020 + addi r6, 32, r6 + bgt/l r7, r6, tr1 + + add r2, r63, r6 +2: + st.q r6, 0, r63 + st.q r6, 8, r63 + st.q r6, 16, r63 + st.q r6, 24, r63 + addi r6, 32, r6 + bgt/l r7, r6, tr2 + + blink tr0, r63 + + diff -puN /dev/null arch/sh/lib64/copy_page.S --- /dev/null +++ a/arch/sh/lib64/copy_page.S @@ -0,0 +1,89 @@ +/* + Copyright 2003 Richard Curnow, SuperH (UK) Ltd. + + This file is subject to the terms and conditions of the GNU General Public + License. See the file "COPYING" in the main directory of this archive + for more details. + + Tight version of mempy for the case of just copying a page. + Prefetch strategy empirically optimised against RTL simulations + of SH5-101 cut2 eval chip with Cayman board DDR memory. + + Parameters: + r2 : destination effective address (start of page) + r3 : source effective address (start of page) + + Always copies 4096 bytes. + + Points to review. + * Currently the prefetch is 4 lines ahead and the alloco is 2 lines ahead. + It seems like the prefetch needs to be at at least 4 lines ahead to get + the data into the cache in time, and the allocos contend with outstanding + prefetches for the same cache set, so it's better to have the numbers + different. + */ + + .section .text..SHmedia32,"ax" + .little + + .balign 8 + .global copy_page +copy_page: + + /* Copy 4096 bytes worth of data from r3 to r2. + Do prefetches 4 lines ahead. + Do alloco 2 lines ahead */ + + pta 1f, tr1 + pta 2f, tr2 + pta 3f, tr3 + ptabs r18, tr0 + +#if 0 + /* TAKum03020 */ + ld.q r3, 0x00, r63 + ld.q r3, 0x20, r63 + ld.q r3, 0x40, r63 + ld.q r3, 0x60, r63 +#endif + alloco r2, 0x00 + synco ! TAKum03020 + alloco r2, 0x20 + synco ! TAKum03020 + + movi 3968, r6 + add r2, r6, r6 + addi r6, 64, r7 + addi r7, 64, r8 + sub r3, r2, r60 + addi r60, 8, r61 + addi r61, 8, r62 + addi r62, 8, r23 + addi r60, 0x80, r22 + +/* Minimal code size. The extra branches inside the loop don't cost much + because they overlap with the time spent waiting for prefetches to + complete. */ +1: +#if 0 + /* TAKum03020 */ + bge/u r2, r6, tr2 ! skip prefetch for last 4 lines + ldx.q r2, r22, r63 ! prefetch 4 lines hence +#endif +2: + bge/u r2, r7, tr3 ! skip alloco for last 2 lines + alloco r2, 0x40 ! alloc destination line 2 lines ahead + synco ! TAKum03020 +3: + ldx.q r2, r60, r36 + ldx.q r2, r61, r37 + ldx.q r2, r62, r38 + ldx.q r2, r23, r39 + st.q r2, 0, r36 + st.q r2, 8, r37 + st.q r2, 16, r38 + st.q r2, 24, r39 + addi r2, 32, r2 + bgt/l r8, r2, tr1 + + blink tr0, r63 ! return diff -puN /dev/null arch/sh/lib64/copy_user_memcpy.S --- /dev/null +++ a/arch/sh/lib64/copy_user_memcpy.S @@ -0,0 +1,217 @@ +! +! Fast SH memcpy +! +! by Toshiyasu Morita (tm@netcom.com) +! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut) +! SH5 code Copyright 2002 SuperH Ltd. +! +! Entry: ARG0: destination pointer +! ARG1: source pointer +! ARG2: byte count +! +! Exit: RESULT: destination pointer +! any other registers in the range r0-r7: trashed +! +! Notes: Usually one wants to do small reads and write a longword, but +! unfortunately it is difficult in some cases to concatanate bytes +! into a longword on the SH, so this does a longword read and small +! writes. +! +! This implementation makes two assumptions about how it is called: +! +! 1.: If the byte count is nonzero, the address of the last byte to be +! copied is unsigned greater than the address of the first byte to +! be copied. This could be easily swapped for a signed comparison, +! but the algorithm used needs some comparison. +! +! 2.: When there are two or three bytes in the last word of an 11-or-more +! bytes memory chunk to b copied, the rest of the word can be read +! without side effects. +! This could be easily changed by increasing the minumum size of +! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, +! however, this would cost a few extra cyles on average. +! For SHmedia, the assumption is that any quadword can be read in its +! enirety if at least one byte is included in the copy. + +/* Imported into Linux kernel by Richard Curnow. This is used to implement the + __copy_user function in the general case, so it has to be a distinct + function from intra-kernel memcpy to allow for exception fix-ups in the + event that the user pointer is bad somewhere in the copy (e.g. due to + running off the end of the vma). + + Note, this algorithm will be slightly wasteful in the case where the source + and destination pointers are equally aligned, because the stlo/sthi pairs + could then be merged back into single stores. If there are a lot of cache + misses, this is probably offset by the stall lengths on the preloads. + +*/ + +/* NOTE : Prefetches removed and allocos guarded by synco to avoid TAKum03020 + * erratum. The first two prefetches are nop-ed out to avoid upsetting the + * instruction counts used in the jump address calculation. + * */ + + .section .text..SHmedia32,"ax" + .little + .balign 32 + .global copy_user_memcpy + .global copy_user_memcpy_end +copy_user_memcpy: + +#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1 +#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1 +#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1 +#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1 + + nop ! ld.b r3,0,r63 ! TAKum03020 + pta/l Large,tr0 + movi 25,r0 + bgeu/u r4,r0,tr0 + nsb r4,r0 + shlli r0,5,r0 + movi (L1-L0+63*32 + 1) & 0xffff,r1 + sub r1, r0, r0 +L0: ptrel r0,tr0 + add r2,r4,r5 + ptabs r18,tr1 + add r3,r4,r6 + blink tr0,r63 + +/* Rearranged to make cut2 safe */ + .balign 8 +L4_7: /* 4..7 byte memcpy cntd. */ + stlo.l r2, 0, r0 + or r6, r7, r6 + sthi.l r5, -1, r6 + stlo.l r5, -4, r6 + blink tr1,r63 + + .balign 8 +L1: /* 0 byte memcpy */ + nop + blink tr1,r63 + nop + nop + nop + nop + +L2_3: /* 2 or 3 byte memcpy cntd. */ + st.b r5,-1,r6 + blink tr1,r63 + + /* 1 byte memcpy */ + ld.b r3,0,r0 + st.b r2,0,r0 + blink tr1,r63 + +L8_15: /* 8..15 byte memcpy cntd. */ + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + + /* 2 or 3 byte memcpy */ + ld.b r3,0,r0 + nop ! ld.b r2,0,r63 ! TAKum03020 + ld.b r3,1,r1 + st.b r2,0,r0 + pta/l L2_3,tr0 + ld.b r6,-1,r6 + st.b r2,1,r1 + blink tr0, r63 + + /* 4 .. 7 byte memcpy */ + LDUAL (r3, 0, r0, r1) + pta L4_7, tr0 + ldlo.l r6, -4, r7 + or r0, r1, r0 + sthi.l r2, 3, r0 + ldhi.l r6, -1, r6 + blink tr0, r63 + + /* 8 .. 15 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + pta L8_15, tr0 + ldlo.q r6, -8, r7 + or r0, r1, r0 + sthi.q r2, 7, r0 + ldhi.q r6, -1, r6 + blink tr0, r63 + + /* 16 .. 24 byte memcpy */ + LDUAQ (r3, 0, r0, r1) + LDUAQ (r3, 8, r8, r9) + or r0, r1, r0 + sthi.q r2, 7, r0 + or r8, r9, r8 + sthi.q r2, 15, r8 + ldlo.q r6, -8, r7 + ldhi.q r6, -1, r6 + stlo.q r2, 8, r8 + stlo.q r2, 0, r0 + or r6, r7, r6 + sthi.q r5, -1, r6 + stlo.q r5, -8, r6 + blink tr1,r63 + +Large: + ! ld.b r2, 0, r63 ! TAKum03020 + pta/l Loop_ua, tr1 + ori r3, -8, r7 + sub r2, r7, r22 + sub r3, r2, r6 + add r2, r4, r5 + ldlo.q r3, 0, r0 + addi r5, -16, r5 + movi 64+8, r27 ! could subtract r7 from that. + stlo.q r2, 0, r0 + sthi.q r2, 7, r0 + ldx.q r22, r6, r0 + bgtu/l r27, r4, tr1 + + addi r5, -48, r27 + pta/l Loop_line, tr0 + addi r6, 64, r36 + addi r6, -24, r19 + addi r6, -16, r20 + addi r6, -8, r21 + +Loop_line: + ! ldx.q r22, r36, r63 ! TAKum03020 + alloco r22, 32 + synco + addi r22, 32, r22 + ldx.q r22, r19, r23 + sthi.q r22, -25, r0 + ldx.q r22, r20, r24 + ldx.q r22, r21, r25 + stlo.q r22, -32, r0 + ldx.q r22, r6, r0 + sthi.q r22, -17, r23 + sthi.q r22, -9, r24 + sthi.q r22, -1, r25 + stlo.q r22, -24, r23 + stlo.q r22, -16, r24 + stlo.q r22, -8, r25 + bgeu r27, r22, tr0 + +Loop_ua: + addi r22, 8, r22 + sthi.q r22, -1, r0 + stlo.q r22, -8, r0 + ldx.q r22, r6, r0 + bgtu/l r5, r22, tr1 + + add r3, r4, r7 + ldlo.q r7, -8, r1 + sthi.q r22, 7, r0 + ldhi.q r7, -1, r7 + ptabs r18,tr1 + stlo.q r22, 0, r0 + or r1, r7, r1 + sthi.q r5, 15, r1 + stlo.q r5, 8, r1 + blink tr1, r63 +copy_user_memcpy_end: + nop diff -puN /dev/null arch/sh/lib64/dbg.c --- /dev/null +++ a/arch/sh/lib64/dbg.c @@ -0,0 +1,430 @@ +/*-------------------------------------------------------------------------- +-- +-- Identity : Linux50 Debug Funcions +-- +-- File : arch/sh/lib64/dbg.c +-- +-- Copyright 2000, 2001 STMicroelectronics Limited. +-- Copyright 2004 Richard Curnow (evt_debug etc) +-- +--------------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +typedef u64 regType_t; + +static regType_t getConfigReg(u64 id) +{ + register u64 reg __asm__("r2"); + asm volatile ("getcfg %1, 0, %0":"=r" (reg):"r"(id)); + return (reg); +} + +/* ======================================================================= */ + +static char *szTab[] = { "4k", "64k", "1M", "512M" }; +static char *protTab[] = { "----", + "---R", + "--X-", + "--XR", + "-W--", + "-W-R", + "-WX-", + "-WXR", + "U---", + "U--R", + "U-X-", + "U-XR", + "UW--", + "UW-R", + "UWX-", + "UWXR" +}; +#define ITLB_BASE 0x00000000 +#define DTLB_BASE 0x00800000 +#define MAX_TLBs 64 +/* PTE High */ +#define GET_VALID(pte) ((pte) & 0x1) +#define GET_SHARED(pte) ((pte) & 0x2) +#define GET_ASID(pte) ((pte >> 2) & 0x0ff) +#define GET_EPN(pte) ((pte) & 0xfffff000) + +/* PTE Low */ +#define GET_CBEHAVIOR(pte) ((pte) & 0x3) +#define GET_PAGE_SIZE(pte) szTab[((pte >> 3) & 0x3)] +#define GET_PROTECTION(pte) protTab[((pte >> 6) & 0xf)] +#define GET_PPN(pte) ((pte) & 0xfffff000) + +#define PAGE_1K_MASK 0x00000000 +#define PAGE_4K_MASK 0x00000010 +#define PAGE_64K_MASK 0x00000080 +#define MMU_PAGESIZE_MASK (PAGE_64K_MASK | PAGE_4K_MASK) +#define PAGE_1MB_MASK MMU_PAGESIZE_MASK +#define PAGE_1K (1024) +#define PAGE_4K (1024 * 4) +#define PAGE_64K (1024 * 64) +#define PAGE_1MB (1024 * 1024) + +#define HOW_TO_READ_TLB_CONTENT \ + "[ ID] PPN EPN ASID Share CB P.Size PROT.\n" + +void print_single_tlb(unsigned long tlb, int single_print) +{ + regType_t pteH; + regType_t pteL; + unsigned int valid, shared, asid, epn, cb, ppn; + char *pSize; + char *pProt; + + /* + ** in case of single print is true, this implies: + ** 1) print the TLB in any case also if NOT VALID + ** 2) print out the header + */ + + pteH = getConfigReg(tlb); + valid = GET_VALID(pteH); + if (single_print) + printk(HOW_TO_READ_TLB_CONTENT); + else if (!valid) + return; + + pteL = getConfigReg(tlb + 1); + + shared = GET_SHARED(pteH); + asid = GET_ASID(pteH); + epn = GET_EPN(pteH); + cb = GET_CBEHAVIOR(pteL); + pSize = GET_PAGE_SIZE(pteL); + pProt = GET_PROTECTION(pteL); + ppn = GET_PPN(pteL); + printk("[%c%2ld] 0x%08x 0x%08x %03d %02x %02x %4s %s\n", + ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP), + ppn, epn, asid, shared, cb, pSize, pProt); +} + +void print_dtlb(void) +{ + int count; + unsigned long tlb; + + printk(" ================= SH-5 D-TLBs Status ===================\n"); + printk(HOW_TO_READ_TLB_CONTENT); + tlb = DTLB_BASE; + for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) + print_single_tlb(tlb, 0); + printk + (" =============================================================\n"); +} + +void print_itlb(void) +{ + int count; + unsigned long tlb; + + printk(" ================= SH-5 I-TLBs Status ===================\n"); + printk(HOW_TO_READ_TLB_CONTENT); + tlb = ITLB_BASE; + for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) + print_single_tlb(tlb, 0); + printk + (" =============================================================\n"); +} + +/* ======================================================================= */ + +#ifdef CONFIG_POOR_MANS_STRACE + +#include "syscalltab.h" + +struct ring_node { + int evt; + int ret_addr; + int event; + int tra; + int pid; + unsigned long sp; + unsigned long pc; +}; + +static struct ring_node event_ring[16]; +static int event_ptr = 0; + +struct stored_syscall_data { + int pid; + int syscall_number; +}; + +#define N_STORED_SYSCALLS 16 + +static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS]; +static int syscall_next=0; +static int syscall_next_print=0; + +void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) +{ + int syscallno = tra & 0xff; + unsigned long sp; + unsigned long stack_bottom; + int pid; + struct ring_node *rr; + + pid = current->pid; + stack_bottom = (unsigned long) task_stack_page(current); + asm volatile("ori r15, 0, %0" : "=r" (sp)); + rr = event_ring + event_ptr; + rr->evt = evt; + rr->ret_addr = ret_addr; + rr->event = event; + rr->tra = tra; + rr->pid = pid; + rr->sp = sp; + rr->pc = regs->pc; + + if (sp < stack_bottom + 3092) { + printk("evt_debug : stack underflow report\n"); + int i, j; + for (j=0, i = event_ptr; j<16; j++) { + rr = event_ring + i; + printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n", + rr->evt, rr->event, rr->tra, rr->pid, rr->sp, rr->pc); + i--; + i &= 15; + } + panic("STACK UNDERFLOW\n"); + } + + event_ptr = (event_ptr + 1) & 15; + + if ((event == 2) && (evt == 0x160)) { + if (syscallno < NUM_SYSCALL_INFO_ENTRIES) { + /* Store the syscall information to print later. We + * can't print this now - currently we're running with + * SR.BL=1, so we can't take a tlbmiss (which could occur + * in the console drivers under printk). + * + * Just overwrite old entries on ring overflow - this + * is only for last-hope debugging. */ + stored_syscalls[syscall_next].pid = current->pid; + stored_syscalls[syscall_next].syscall_number = syscallno; + syscall_next++; + syscall_next &= (N_STORED_SYSCALLS - 1); + } + } +} + +static void drain_syscalls(void) { + while (syscall_next_print != syscall_next) { + printk("Task %d: %s()\n", + stored_syscalls[syscall_next_print].pid, + syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name); + syscall_next_print++; + syscall_next_print &= (N_STORED_SYSCALLS - 1); + } +} + +void evt_debug2(unsigned int ret) +{ + drain_syscalls(); + printk("Task %d: syscall returns %08x\n", current->pid, ret); +} + +void evt_debug_ret_from_irq(struct pt_regs *regs) +{ + int pid; + struct ring_node *rr; + + pid = current->pid; + rr = event_ring + event_ptr; + rr->evt = 0xffff; + rr->ret_addr = 0; + rr->event = 0; + rr->tra = 0; + rr->pid = pid; + rr->pc = regs->pc; + event_ptr = (event_ptr + 1) & 15; +} + +void evt_debug_ret_from_exc(struct pt_regs *regs) +{ + int pid; + struct ring_node *rr; + + pid = current->pid; + rr = event_ring + event_ptr; + rr->evt = 0xfffe; + rr->ret_addr = 0; + rr->event = 0; + rr->tra = 0; + rr->pid = pid; + rr->pc = regs->pc; + event_ptr = (event_ptr + 1) & 15; +} + +#endif /* CONFIG_POOR_MANS_STRACE */ + +/* ======================================================================= */ + +void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs) +{ + + unsigned long long ah, al, bh, bl, ch, cl; + + printk("\n"); + printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n", + ((from) ? from : "???"), current->pid, trapnr, signr); + + asm volatile ("getcon " __EXPEVT ", %0":"=r"(ah)); + asm volatile ("getcon " __EXPEVT ", %0":"=r"(al)); + ah = (ah) >> 32; + al = (al) & 0xffffffff; + asm volatile ("getcon " __KCR1 ", %0":"=r"(bh)); + asm volatile ("getcon " __KCR1 ", %0":"=r"(bl)); + bh = (bh) >> 32; + bl = (bl) & 0xffffffff; + asm volatile ("getcon " __INTEVT ", %0":"=r"(ch)); + asm volatile ("getcon " __INTEVT ", %0":"=r"(cl)); + ch = (ch) >> 32; + cl = (cl) & 0xffffffff; + printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + asm volatile ("getcon " __PEXPEVT ", %0":"=r"(ah)); + asm volatile ("getcon " __PEXPEVT ", %0":"=r"(al)); + ah = (ah) >> 32; + al = (al) & 0xffffffff; + asm volatile ("getcon " __PSPC ", %0":"=r"(bh)); + asm volatile ("getcon " __PSPC ", %0":"=r"(bl)); + bh = (bh) >> 32; + bl = (bl) & 0xffffffff; + asm volatile ("getcon " __PSSR ", %0":"=r"(ch)); + asm volatile ("getcon " __PSSR ", %0":"=r"(cl)); + ch = (ch) >> 32; + cl = (cl) & 0xffffffff; + printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->pc) >> 32; + al = (regs->pc) & 0xffffffff; + bh = (regs->regs[18]) >> 32; + bl = (regs->regs[18]) & 0xffffffff; + ch = (regs->regs[15]) >> 32; + cl = (regs->regs[15]) & 0xffffffff; + printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->sr) >> 32; + al = (regs->sr) & 0xffffffff; + asm volatile ("getcon " __TEA ", %0":"=r"(bh)); + asm volatile ("getcon " __TEA ", %0":"=r"(bl)); + bh = (bh) >> 32; + bl = (bl) & 0xffffffff; + asm volatile ("getcon " __KCR0 ", %0":"=r"(ch)); + asm volatile ("getcon " __KCR0 ", %0":"=r"(cl)); + ch = (ch) >> 32; + cl = (cl) & 0xffffffff; + printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[0]) >> 32; + al = (regs->regs[0]) & 0xffffffff; + bh = (regs->regs[1]) >> 32; + bl = (regs->regs[1]) & 0xffffffff; + ch = (regs->regs[2]) >> 32; + cl = (regs->regs[2]) & 0xffffffff; + printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[3]) >> 32; + al = (regs->regs[3]) & 0xffffffff; + bh = (regs->regs[4]) >> 32; + bl = (regs->regs[4]) & 0xffffffff; + ch = (regs->regs[5]) >> 32; + cl = (regs->regs[5]) & 0xffffffff; + printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[6]) >> 32; + al = (regs->regs[6]) & 0xffffffff; + bh = (regs->regs[7]) >> 32; + bl = (regs->regs[7]) & 0xffffffff; + ch = (regs->regs[8]) >> 32; + cl = (regs->regs[8]) & 0xffffffff; + printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + + ah = (regs->regs[9]) >> 32; + al = (regs->regs[9]) & 0xffffffff; + bh = (regs->regs[10]) >> 32; + bl = (regs->regs[10]) & 0xffffffff; + ch = (regs->regs[11]) >> 32; + cl = (regs->regs[11]) & 0xffffffff; + printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + printk("....\n"); + + ah = (regs->tregs[0]) >> 32; + al = (regs->tregs[0]) & 0xffffffff; + bh = (regs->tregs[1]) >> 32; + bl = (regs->tregs[1]) & 0xffffffff; + ch = (regs->tregs[2]) >> 32; + cl = (regs->tregs[2]) & 0xffffffff; + printk("T0 : %08Lx%08Lx T1 : %08Lx%08Lx T2 : %08Lx%08Lx\n", + ah, al, bh, bl, ch, cl); + printk("....\n"); + + print_dtlb(); + print_itlb(); +} + +/* ======================================================================= */ + +/* +** Depending on scan the MMU, Data or Instruction side +** looking for a valid mapping matching Eaddr & asid. +** Return -1 if not found or the TLB id entry otherwise. +** Note: it works only for 4k pages! +*/ +static unsigned long +lookup_mmu_side(unsigned long base, unsigned long Eaddr, unsigned long asid) +{ + regType_t pteH; + unsigned long epn; + int count; + + epn = Eaddr & 0xfffff000; + + for (count = 0; count < MAX_TLBs; count++, base += TLB_STEP) { + pteH = getConfigReg(base); + if (GET_VALID(pteH)) + if ((unsigned long) GET_EPN(pteH) == epn) + if ((unsigned long) GET_ASID(pteH) == asid) + break; + } + return ((unsigned long) ((count < MAX_TLBs) ? base : -1)); +} + +unsigned long lookup_dtlb(unsigned long Eaddr) +{ + unsigned long asid = get_asid(); + return (lookup_mmu_side((u64) DTLB_BASE, Eaddr, asid)); +} + +unsigned long lookup_itlb(unsigned long Eaddr) +{ + unsigned long asid = get_asid(); + return (lookup_mmu_side((u64) ITLB_BASE, Eaddr, asid)); +} + +void print_page(struct page *page) +{ + printk(" page[%p] -> index 0x%lx, count 0x%x, flags 0x%lx\n", + page, page->index, page_count(page), page->flags); + printk(" address_space = %p, pages =%ld\n", page->mapping, + page->mapping->nrpages); + +} diff -puN /dev/null arch/sh/lib64/memcpy.c --- /dev/null +++ a/arch/sh/lib64/memcpy.c @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2002 Mark Debbage (Mark.Debbage@superh.com) + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + */ + +#include +#include + +// This is a simplistic optimization of memcpy to increase the +// granularity of access beyond one byte using aligned +// loads and stores. This is not an optimal implementation +// for SH-5 (especially with regard to prefetching and the cache), +// and a better version should be provided later ... + +void *memcpy(void *dest, const void *src, size_t count) +{ + char *d = (char *) dest, *s = (char *) src; + + if (count >= 32) { + int i = 8 - (((unsigned long) d) & 0x7); + + if (i != 8) + while (i-- && count--) { + *d++ = *s++; + } + + if (((((unsigned long) d) & 0x7) == 0) && + ((((unsigned long) s) & 0x7) == 0)) { + while (count >= 32) { + unsigned long long t1, t2, t3, t4; + t1 = *(unsigned long long *) (s); + t2 = *(unsigned long long *) (s + 8); + t3 = *(unsigned long long *) (s + 16); + t4 = *(unsigned long long *) (s + 24); + *(unsigned long long *) (d) = t1; + *(unsigned long long *) (d + 8) = t2; + *(unsigned long long *) (d + 16) = t3; + *(unsigned long long *) (d + 24) = t4; + d += 32; + s += 32; + count -= 32; + } + while (count >= 8) { + *(unsigned long long *) d = + *(unsigned long long *) s; + d += 8; + s += 8; + count -= 8; + } + } + + if (((((unsigned long) d) & 0x3) == 0) && + ((((unsigned long) s) & 0x3) == 0)) { + while (count >= 4) { + *(unsigned long *) d = *(unsigned long *) s; + d += 4; + s += 4; + count -= 4; + } + } + + if (((((unsigned long) d) & 0x1) == 0) && + ((((unsigned long) s) & 0x1) == 0)) { + while (count >= 2) { + *(unsigned short *) d = *(unsigned short *) s; + d += 2; + s += 2; + count -= 2; + } + } + } + + while (count--) { + *d++ = *s++; + } + + return d; +} diff -puN /dev/null arch/sh/lib64/panic.c --- /dev/null +++ a/arch/sh/lib64/panic.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2003 Richard Curnow, SuperH UK Limited + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include + +/* THIS IS A PHYSICAL ADDRESS */ +#define HDSP2534_ADDR (0x04002100) + +#ifdef CONFIG_SH_CAYMAN + +static void poor_mans_delay(void) +{ + int i; + for (i = 0; i < 2500000; i++) { + } /* poor man's delay */ +} + +static void show_value(unsigned long x) +{ + int i; + unsigned nibble; + for (i = 0; i < 8; i++) { + nibble = ((x >> (i * 4)) & 0xf); + + ctrl_outb(nibble + ((nibble > 9) ? 55 : 48), + HDSP2534_ADDR + 0xe0 + ((7 - i) << 2)); + } +} + +#endif + +void +panic_handler(unsigned long panicPC, unsigned long panicSSR, + unsigned long panicEXPEVT) +{ +#ifdef CONFIG_SH_CAYMAN + while (1) { + /* This piece of code displays the PC on the LED display */ + show_value(panicPC); + poor_mans_delay(); + show_value(panicSSR); + poor_mans_delay(); + show_value(panicEXPEVT); + poor_mans_delay(); + } +#endif + + /* Never return from the panic handler */ + for (;;) ; + +} diff -puN /dev/null arch/sh/lib64/udelay.c --- /dev/null +++ a/arch/sh/lib64/udelay.c @@ -0,0 +1,56 @@ +/* + * arch/sh/lib64/udelay.c + * + * Delay routines, using a pre-computed "loops_per_jiffy" value. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include + +/* + * Use only for very small delays (< 1 msec). + * + * The active part of our cycle counter is only 32-bits wide, and + * we're treating the difference between two marks as signed. On + * a 1GHz box, that's about 2 seconds. + */ + +void __delay(int loops) +{ + long long dummy; + __asm__ __volatile__("gettr tr0, %1\n\t" + "pta $+4, tr0\n\t" + "addi %0, -1, %0\n\t" + "bne %0, r63, tr0\n\t" + "ptabs %1, tr0\n\t":"=r"(loops), + "=r"(dummy) + :"0"(loops)); +} + +void __udelay(unsigned long long usecs, unsigned long lpj) +{ + usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj; + __delay((long long) usecs >> 32); +} + +void __ndelay(unsigned long long nsecs, unsigned long lpj) +{ + nsecs *= (((unsigned long long) HZ << 32) / 1000000000) * lpj; + __delay((long long) nsecs >> 32); +} + +void udelay(unsigned long usecs) +{ + __udelay(usecs, cpu_data[raw_smp_processor_id()].loops_per_jiffy); +} + +void ndelay(unsigned long nsecs) +{ + __ndelay(nsecs, cpu_data[raw_smp_processor_id()].loops_per_jiffy); +} diff -puN arch/sh/mm/Kconfig~git-sh arch/sh/mm/Kconfig --- a/arch/sh/mm/Kconfig~git-sh +++ a/arch/sh/mm/Kconfig @@ -1,193 +1,3 @@ -# -# Processor families -# -config CPU_SH2 - bool - -config CPU_SH2A - bool - select CPU_SH2 - -config CPU_SH3 - bool - select CPU_HAS_INTEVT - select CPU_HAS_SR_RB - -config CPU_SH4 - bool - select CPU_HAS_INTEVT - select CPU_HAS_SR_RB - select CPU_HAS_PTEA if !CPU_SH4A || CPU_SHX2 - select CPU_HAS_FPU if !CPU_SH4AL_DSP - -config CPU_SH4A - bool - select CPU_SH4 - -config CPU_SH4AL_DSP - bool - select CPU_SH4A - select CPU_HAS_DSP - -config CPU_SHX2 - bool - -config CPU_SHX3 - bool - -choice - prompt "Processor sub-type selection" - -# -# Processor subtypes -# - -# SH-2 Processor Support - -config CPU_SUBTYPE_SH7619 - bool "Support SH7619 processor" - select CPU_SH2 - -# SH-2A Processor Support - -config CPU_SUBTYPE_SH7206 - bool "Support SH7206 processor" - select CPU_SH2A - -# SH-3 Processor Support - -config CPU_SUBTYPE_SH7705 - bool "Support SH7705 processor" - select CPU_SH3 - -config CPU_SUBTYPE_SH7706 - bool "Support SH7706 processor" - select CPU_SH3 - help - Select SH7706 if you have a 133 Mhz SH-3 HD6417706 CPU. - -config CPU_SUBTYPE_SH7707 - bool "Support SH7707 processor" - select CPU_SH3 - help - Select SH7707 if you have a 60 Mhz SH-3 HD6417707 CPU. - -config CPU_SUBTYPE_SH7708 - bool "Support SH7708 processor" - select CPU_SH3 - help - Select SH7708 if you have a 60 Mhz SH-3 HD6417708S or - if you have a 100 Mhz SH-3 HD6417708R CPU. - -config CPU_SUBTYPE_SH7709 - bool "Support SH7709 processor" - select CPU_SH3 - help - Select SH7709 if you have a 80 Mhz SH-3 HD6417709 CPU. - -config CPU_SUBTYPE_SH7710 - bool "Support SH7710 processor" - select CPU_SH3 - select CPU_HAS_DSP - help - Select SH7710 if you have a SH3-DSP SH7710 CPU. - -config CPU_SUBTYPE_SH7712 - bool "Support SH7712 processor" - select CPU_SH3 - select CPU_HAS_DSP - help - Select SH7712 if you have a SH3-DSP SH7712 CPU. - -config CPU_SUBTYPE_SH7720 - bool "Support SH7720 processor" - select CPU_SH3 - select CPU_HAS_DSP - help - Select SH7720 if you have a SH3-DSP SH7720 CPU. - -# SH-4 Processor Support - -config CPU_SUBTYPE_SH7750 - bool "Support SH7750 processor" - select CPU_SH4 - help - Select SH7750 if you have a 200 Mhz SH-4 HD6417750 CPU. - -config CPU_SUBTYPE_SH7091 - bool "Support SH7091 processor" - select CPU_SH4 - help - Select SH7091 if you have an SH-4 based Sega device (such as - the Dreamcast, Naomi, and Naomi 2). - -config CPU_SUBTYPE_SH7750R - bool "Support SH7750R processor" - select CPU_SH4 - -config CPU_SUBTYPE_SH7750S - bool "Support SH7750S processor" - select CPU_SH4 - -config CPU_SUBTYPE_SH7751 - bool "Support SH7751 processor" - select CPU_SH4 - help - Select SH7751 if you have a 166 Mhz SH-4 HD6417751 CPU, - or if you have a HD6417751R CPU. - -config CPU_SUBTYPE_SH7751R - bool "Support SH7751R processor" - select CPU_SH4 - -config CPU_SUBTYPE_SH7760 - bool "Support SH7760 processor" - select CPU_SH4 - -config CPU_SUBTYPE_SH4_202 - bool "Support SH4-202 processor" - select CPU_SH4 - -# SH-4A Processor Support - -config CPU_SUBTYPE_SH7770 - bool "Support SH7770 processor" - select CPU_SH4A - -config CPU_SUBTYPE_SH7780 - bool "Support SH7780 processor" - select CPU_SH4A - -config CPU_SUBTYPE_SH7785 - bool "Support SH7785 processor" - select CPU_SH4A - select CPU_SHX2 - select ARCH_SPARSEMEM_ENABLE - select SYS_SUPPORTS_NUMA - -config CPU_SUBTYPE_SHX3 - bool "Support SH-X3 processor" - select CPU_SH4A - select CPU_SHX3 - select ARCH_SPARSEMEM_ENABLE - select SYS_SUPPORTS_NUMA - select SYS_SUPPORTS_SMP - -# SH4AL-DSP Processor Support - -config CPU_SUBTYPE_SH7343 - bool "Support SH7343 processor" - select CPU_SH4AL_DSP - -config CPU_SUBTYPE_SH7722 - bool "Support SH7722 processor" - select CPU_SH4AL_DSP - select CPU_SHX2 - select ARCH_SPARSEMEM_ENABLE - select SYS_SUPPORTS_NUMA - -endchoice - menu "Memory management options" config QUICKLIST @@ -207,7 +17,8 @@ config MMU config PAGE_OFFSET hex - default "0x80000000" if MMU + default "0x80000000" if MMU && SUPERH32 + default "0x20000000" if MMU && SUPERH64 default "0x00000000" config MEMORY_START @@ -228,17 +39,28 @@ config MEMORY_START config MEMORY_SIZE hex "Physical memory size" - default "0x00400000" + default "0x04000000" help This sets the default memory size assumed by your SH kernel. It can be overridden as normal by the 'mem=' argument on the kernel command line. If unsure, consult your board specifications or just leave it - as 0x00400000 which was the default value before this became + as 0x04000000 which was the default value before this became configurable. +# Physical addressing modes + +config 29BIT + def_bool !32BIT + depends on SUPERH32 + config 32BIT + bool + default y if CPU_SH5 + +config PMB bool "Support 32-bit physical addressing through PMB" depends on MMU && (CPU_SUBTYPE_SH7780 || CPU_SUBTYPE_SH7785) + select 32BIT default y help If you say Y here, physical addressing will be extended to @@ -256,7 +78,7 @@ config X2TLB config VSYSCALL bool "Support vsyscall page" - depends on MMU + depends on MMU && (CPU_SH3 || CPU_SH4) default y help This will enable support for the kernel mapping a vDSO page @@ -335,7 +157,7 @@ config PAGE_SIZE_8KB config PAGE_SIZE_64KB bool "64kB" - depends on CPU_SH4 + depends on CPU_SH4 || CPU_SH5 help This enables support for 64kB pages, possible on all SH-4 CPUs and later. @@ -344,7 +166,7 @@ endchoice choice prompt "HugeTLB page size" - depends on HUGETLB_PAGE && CPU_SH4 && MMU + depends on HUGETLB_PAGE && (CPU_SH4 || CPU_SH5) && MMU default HUGETLB_PAGE_SIZE_64K config HUGETLB_PAGE_SIZE_64K @@ -365,6 +187,10 @@ config HUGETLB_PAGE_SIZE_64MB bool "64MB" depends on X2TLB +config HUGETLB_PAGE_SIZE_512MB + bool "512MB" + depends on CPU_SH5 + endchoice source "mm/Kconfig" @@ -392,12 +218,12 @@ config SH_DIRECT_MAPPED choice prompt "Cache mode" - default CACHE_WRITEBACK if CPU_SH2A || CPU_SH3 || CPU_SH4 + default CACHE_WRITEBACK if CPU_SH2A || CPU_SH3 || CPU_SH4 || CPU_SH5 default CACHE_WRITETHROUGH if (CPU_SH2 && !CPU_SH2A) config CACHE_WRITEBACK bool "Write-back" - depends on CPU_SH2A || CPU_SH3 || CPU_SH4 + depends on CPU_SH2A || CPU_SH3 || CPU_SH4 || CPU_SH5 config CACHE_WRITETHROUGH bool "Write-through" diff -puN arch/sh/mm/Makefile~git-sh arch/sh/mm/Makefile --- a/arch/sh/mm/Makefile~git-sh +++ a/arch/sh/mm/Makefile @@ -1,37 +1,5 @@ -# -# Makefile for the Linux SuperH-specific parts of the memory manager. -# - -obj-y := init.o extable.o consistent.o - -ifndef CONFIG_CACHE_OFF -obj-$(CONFIG_CPU_SH2) += cache-sh2.o -obj-$(CONFIG_CPU_SH3) += cache-sh3.o -obj-$(CONFIG_CPU_SH4) += cache-sh4.o -obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o +ifeq ($(CONFIG_SUPERH32),y) +include ${srctree}/arch/sh/mm/Makefile_32 +else +include ${srctree}/arch/sh/mm/Makefile_64 endif - -mmu-y := tlb-nommu.o pg-nommu.o -mmu-$(CONFIG_MMU) := fault.o clear_page.o copy_page.o tlb-flush.o \ - ioremap.o - -obj-y += $(mmu-y) - -ifdef CONFIG_DEBUG_FS -obj-$(CONFIG_CPU_SH4) += cache-debugfs.o -endif - -ifdef CONFIG_MMU -obj-$(CONFIG_CPU_SH3) += tlb-sh3.o -obj-$(CONFIG_CPU_SH4) += tlb-sh4.o -ifndef CONFIG_CACHE_OFF -obj-$(CONFIG_CPU_SH4) += pg-sh4.o -obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o -endif -endif - -obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o -obj-$(CONFIG_32BIT) += pmb.o -obj-$(CONFIG_NUMA) += numa.o - -EXTRA_CFLAGS += -Werror diff -puN /dev/null arch/sh/mm/Makefile_32 --- /dev/null +++ a/arch/sh/mm/Makefile_32 @@ -0,0 +1,36 @@ +# +# Makefile for the Linux SuperH-specific parts of the memory manager. +# + +obj-y := init.o extable_32.o consistent.o + +ifndef CONFIG_CACHE_OFF +obj-$(CONFIG_CPU_SH2) += cache-sh2.o +obj-$(CONFIG_CPU_SH3) += cache-sh3.o +obj-$(CONFIG_CPU_SH4) += cache-sh4.o +obj-$(CONFIG_SH7705_CACHE_32KB) += cache-sh7705.o +endif + +mmu-y := tlb-nommu.o pg-nommu.o +mmu-$(CONFIG_MMU) := fault_32.o tlbflush_32.o ioremap_32.o + +obj-y += $(mmu-y) + +ifdef CONFIG_DEBUG_FS +obj-$(CONFIG_CPU_SH4) += cache-debugfs.o +endif + +ifdef CONFIG_MMU +obj-$(CONFIG_CPU_SH3) += tlb-sh3.o +obj-$(CONFIG_CPU_SH4) += tlb-sh4.o +ifndef CONFIG_CACHE_OFF +obj-$(CONFIG_CPU_SH4) += pg-sh4.o +obj-$(CONFIG_SH7705_CACHE_32KB) += pg-sh7705.o +endif +endif + +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_PMB) += pmb.o +obj-$(CONFIG_NUMA) += numa.o + +EXTRA_CFLAGS += -Werror diff -puN /dev/null arch/sh/mm/Makefile_64 --- /dev/null +++ a/arch/sh/mm/Makefile_64 @@ -0,0 +1,44 @@ +# +# Makefile for the Linux SuperH-specific parts of the memory manager. +# + +obj-y := init.o extable_64.o consistent.o + +mmu-y := tlb-nommu.o pg-nommu.o +mmu-$(CONFIG_MMU) := fault_64.o ioremap_64.o tlbflush_64.o tlb-sh5.o + +ifndef CONFIG_CACHE_OFF +obj-y += cache-sh5.o +endif + +obj-y += $(mmu-y) + +obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o +obj-$(CONFIG_NUMA) += numa.o + +EXTRA_CFLAGS += -Werror + +# Special flags for fault_64.o. This puts restrictions on the number of +# caller-save registers that the compiler can target when building this file. +# This is required because the code is called from a context in entry.S where +# very few registers have been saved in the exception handler (for speed +# reasons). +# The caller save registers that have been saved and which can be used are +# r2,r3,r4,r5 : argument passing +# r15, r18 : SP and LINK +# tr0-4 : allow all caller-save TR's. The compiler seems to be able to make +# use of them, so it's probably beneficial to performance to save them +# and have them available for it. +# +# The resources not listed below are callee save, i.e. the compiler is free to +# use any of them and will spill them to the stack itself. + +CFLAGS_fault_64.o += -ffixed-r7 \ + -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \ + -ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \ + -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \ + -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \ + -ffixed-r36 -ffixed-r37 -ffixed-r38 -ffixed-r39 -ffixed-r40 \ + -ffixed-r41 -ffixed-r42 -ffixed-r43 \ + -ffixed-r60 -ffixed-r61 -ffixed-r62 \ + -fomit-frame-pointer diff -puN arch/sh/mm/cache-debugfs.c~git-sh arch/sh/mm/cache-debugfs.c --- a/arch/sh/mm/cache-debugfs.c~git-sh +++ a/arch/sh/mm/cache-debugfs.c @@ -22,7 +22,8 @@ enum cache_type { CACHE_TYPE_UNIFIED, }; -static int cache_seq_show(struct seq_file *file, void *iter) +static int __uses_jump_to_uncached cache_seq_show(struct seq_file *file, + void *iter) { unsigned int cache_type = (unsigned int)file->private; struct cache_info *cache; @@ -34,11 +35,11 @@ static int cache_seq_show(struct seq_fil * Go uncached immediately so we don't skew the results any * more than we already are.. */ - jump_to_P2(); + jump_to_uncached(); ccr = ctrl_inl(CCR); if ((ccr & CCR_CACHE_ENABLE) == 0) { - back_to_P1(); + back_to_cached(); seq_printf(file, "disabled\n"); return 0; @@ -104,7 +105,7 @@ static int cache_seq_show(struct seq_fil addrstart += cache->way_incr; } - back_to_P1(); + back_to_cached(); return 0; } diff -puN arch/sh/mm/cache-sh4.c~git-sh arch/sh/mm/cache-sh4.c --- a/arch/sh/mm/cache-sh4.c~git-sh +++ a/arch/sh/mm/cache-sh4.c @@ -190,7 +190,7 @@ void flush_icache_range(unsigned long st * .. which happens to be the same behavior as flush_icache_range(). * So, we simply flush out a line. */ -void flush_cache_sigtramp(unsigned long addr) +void __uses_jump_to_uncached flush_cache_sigtramp(unsigned long addr) { unsigned long v, index; unsigned long flags; @@ -205,13 +205,13 @@ void flush_cache_sigtramp(unsigned long (v & boot_cpu_data.icache.entry_mask); local_irq_save(flags); - jump_to_P2(); + jump_to_uncached(); for (i = 0; i < boot_cpu_data.icache.ways; i++, index += boot_cpu_data.icache.way_incr) ctrl_outl(0, index); /* Clear out Valid-bit */ - back_to_P1(); + back_to_cached(); wmb(); local_irq_restore(flags); } @@ -256,12 +256,12 @@ void flush_dcache_page(struct page *page } /* TODO: Selective icache invalidation through IC address array.. */ -static inline void flush_icache_all(void) +static inline void __uses_jump_to_uncached flush_icache_all(void) { unsigned long flags, ccr; local_irq_save(flags); - jump_to_P2(); + jump_to_uncached(); /* Flush I-cache */ ccr = ctrl_inl(CCR); @@ -269,11 +269,11 @@ static inline void flush_icache_all(void ctrl_outl(ccr, CCR); /* - * back_to_P1() will take care of the barrier for us, don't add + * back_to_cached() will take care of the barrier for us, don't add * another one! */ - back_to_P1(); + back_to_cached(); local_irq_restore(flags); } diff -puN /dev/null arch/sh/mm/cache-sh5.c --- /dev/null +++ a/arch/sh/mm/cache-sh5.c @@ -0,0 +1,1029 @@ +/* + * arch/sh/mm/cache-sh5.c + * + * Original version Copyright (C) 2000, 2001 Paolo Alberelli + * Second version Copyright (C) benedict.gaster@superh.com 2002 + * Third version Copyright Richard.Curnow@superh.com 2003 + * Hacks to third version Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* for flush_itlb_range */ + +#include + +/* This function is in entry.S */ +extern unsigned long switch_and_save_asid(unsigned long new_asid); + +/* Wired TLB entry for the D-cache */ +static unsigned long long dtlb_cache_slot; + +/** + * sh64_cache_init() + * + * This is pretty much just a straightforward clone of the SH + * detect_cpu_and_cache_system(). + * + * This function is responsible for setting up all of the cache + * info dynamically as well as taking care of CPU probing and + * setting up the relevant subtype data. + * + * FIXME: For the time being, we only really support the SH5-101 + * out of the box, and don't support dynamic probing for things + * like the SH5-103 or even cut2 of the SH5-101. Implement this + * later! + */ +int __init sh64_cache_init(void) +{ + /* + * First, setup some sane values for the I-cache. + */ + cpu_data->icache.ways = 4; + cpu_data->icache.sets = 256; + cpu_data->icache.linesz = L1_CACHE_BYTES; + + /* + * FIXME: This can probably be cleaned up a bit as well.. for example, + * do we really need the way shift _and_ the way_step_shift ?? Judging + * by the existing code, I would guess no.. is there any valid reason + * why we need to be tracking this around? + */ + cpu_data->icache.way_shift = 13; + cpu_data->icache.entry_shift = 5; + cpu_data->icache.set_shift = 4; + cpu_data->icache.way_step_shift = 16; + cpu_data->icache.asid_shift = 2; + + /* + * way offset = cache size / associativity, so just don't factor in + * associativity in the first place.. + */ + cpu_data->icache.way_ofs = cpu_data->icache.sets * + cpu_data->icache.linesz; + + cpu_data->icache.asid_mask = 0x3fc; + cpu_data->icache.idx_mask = 0x1fe0; + cpu_data->icache.epn_mask = 0xffffe000; + cpu_data->icache.flags = 0; + + /* + * Next, setup some sane values for the D-cache. + * + * On the SH5, these are pretty consistent with the I-cache settings, + * so we just copy over the existing definitions.. these can be fixed + * up later, especially if we add runtime CPU probing. + * + * Though in the meantime it saves us from having to duplicate all of + * the above definitions.. + */ + cpu_data->dcache = cpu_data->icache; + + /* + * Setup any cache-related flags here + */ +#if defined(CONFIG_DCACHE_WRITE_THROUGH) + set_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)); +#elif defined(CONFIG_DCACHE_WRITE_BACK) + set_bit(SH_CACHE_MODE_WB, &(cpu_data->dcache.flags)); +#endif + + /* + * We also need to reserve a slot for the D-cache in the DTLB, so we + * do this now .. + */ + dtlb_cache_slot = sh64_get_wired_dtlb_entry(); + + return 0; +} + +#ifdef CONFIG_DCACHE_DISABLED +#define sh64_dcache_purge_all() do { } while (0) +#define sh64_dcache_purge_coloured_phy_page(paddr, eaddr) do { } while (0) +#define sh64_dcache_purge_user_range(mm, start, end) do { } while (0) +#define sh64_dcache_purge_phy_page(paddr) do { } while (0) +#define sh64_dcache_purge_virt_page(mm, eaddr) do { } while (0) +#define sh64_dcache_purge_kernel_range(start, end) do { } while (0) +#define sh64_dcache_wback_current_user_range(start, end) do { } while (0) +#endif + +/*##########################################################################*/ + +/* From here onwards, a rewrite of the implementation, + by Richard.Curnow@superh.com. + + The major changes in this compared to the old version are; + 1. use more selective purging through OCBP instead of using ALLOCO to purge + by natural replacement. This avoids purging out unrelated cache lines + that happen to be in the same set. + 2. exploit the APIs copy_user_page and clear_user_page better + 3. be more selective about I-cache purging, in particular use invalidate_all + more sparingly. + + */ + +/*########################################################################## + SUPPORT FUNCTIONS + ##########################################################################*/ + +/****************************************************************************/ +/* The following group of functions deal with mapping and unmapping a temporary + page into the DTLB slot that have been set aside for our exclusive use. */ +/* In order to accomplish this, we use the generic interface for adding and + removing a wired slot entry as defined in arch/sh/mm/tlb-sh5.c */ +/****************************************************************************/ + +static unsigned long slot_own_flags; + +static inline void sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, unsigned long paddr) +{ + local_irq_save(slot_own_flags); + sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr); +} + +static inline void sh64_teardown_dtlb_cache_slot(void) +{ + sh64_teardown_tlb_slot(dtlb_cache_slot); + local_irq_restore(slot_own_flags); +} + +/****************************************************************************/ + +#ifndef CONFIG_ICACHE_DISABLED + +static void __inline__ sh64_icache_inv_all(void) +{ + unsigned long long addr, flag, data; + unsigned int flags; + + addr=ICCR0; + flag=ICCR0_ICI; + data=0; + + /* Make this a critical section for safety (probably not strictly necessary.) */ + local_irq_save(flags); + + /* Without %1 it gets unexplicably wrong */ + asm volatile("getcfg %3, 0, %0\n\t" + "or %0, %2, %0\n\t" + "putcfg %3, 0, %0\n\t" + "synci" + : "=&r" (data) + : "0" (data), "r" (flag), "r" (addr)); + + local_irq_restore(flags); +} + +static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end) +{ + /* Invalidate range of addresses [start,end] from the I-cache, where + * the addresses lie in the kernel superpage. */ + + unsigned long long ullend, addr, aligned_start; +#if (NEFF == 32) + aligned_start = (unsigned long long)(signed long long)(signed long) start; +#else +#error "NEFF != 32" +#endif + aligned_start &= L1_CACHE_ALIGN_MASK; + addr = aligned_start; +#if (NEFF == 32) + ullend = (unsigned long long) (signed long long) (signed long) end; +#else +#error "NEFF != 32" +#endif + while (addr <= ullend) { + asm __volatile__ ("icbi %0, 0" : : "r" (addr)); + addr += L1_CACHE_BYTES; + } +} + +static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long eaddr) +{ + /* If we get called, we know that vma->vm_flags contains VM_EXEC. + Also, eaddr is page-aligned. */ + + unsigned long long addr, end_addr; + unsigned long flags = 0; + unsigned long running_asid, vma_asid; + addr = eaddr; + end_addr = addr + PAGE_SIZE; + + /* Check whether we can use the current ASID for the I-cache + invalidation. For example, if we're called via + access_process_vm->flush_cache_page->here, (e.g. when reading from + /proc), 'running_asid' will be that of the reader, not of the + victim. + + Also, note the risk that we might get pre-empted between the ASID + compare and blocking IRQs, and before we regain control, the + pid->ASID mapping changes. However, the whole cache will get + invalidated when the mapping is renewed, so the worst that can + happen is that the loop below ends up invalidating somebody else's + cache entries. + */ + + running_asid = get_asid(); + vma_asid = (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); + if (running_asid != vma_asid) { + local_irq_save(flags); + switch_and_save_asid(vma_asid); + } + while (addr < end_addr) { + /* Worth unrolling a little */ + asm __volatile__("icbi %0, 0" : : "r" (addr)); + asm __volatile__("icbi %0, 32" : : "r" (addr)); + asm __volatile__("icbi %0, 64" : : "r" (addr)); + asm __volatile__("icbi %0, 96" : : "r" (addr)); + addr += 128; + } + if (running_asid != vma_asid) { + switch_and_save_asid(running_asid); + local_irq_restore(flags); + } +} + +/****************************************************************************/ + +static void sh64_icache_inv_user_page_range(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + /* Used for invalidating big chunks of I-cache, i.e. assume the range + is whole pages. If 'start' or 'end' is not page aligned, the code + is conservative and invalidates to the ends of the enclosing pages. + This is functionally OK, just a performance loss. */ + + /* See the comments below in sh64_dcache_purge_user_range() regarding + the choice of algorithm. However, for the I-cache option (2) isn't + available because there are no physical tags so aliases can't be + resolved. The icbi instruction has to be used through the user + mapping. Because icbi is cheaper than ocbp on a cache hit, it + would be cheaper to use the selective code for a large range than is + possible with the D-cache. Just assume 64 for now as a working + figure. + */ + + int n_pages; + + if (!mm) return; + + n_pages = ((end - start) >> PAGE_SHIFT); + if (n_pages >= 64) { + sh64_icache_inv_all(); + } else { + unsigned long aligned_start; + unsigned long eaddr; + unsigned long after_last_page_start; + unsigned long mm_asid, current_asid; + unsigned long long flags = 0ULL; + + mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; + current_asid = get_asid(); + + if (mm_asid != current_asid) { + /* Switch ASID and run the invalidate loop under cli */ + local_irq_save(flags); + switch_and_save_asid(mm_asid); + } + + aligned_start = start & PAGE_MASK; + after_last_page_start = PAGE_SIZE + ((end - 1) & PAGE_MASK); + + while (aligned_start < after_last_page_start) { + struct vm_area_struct *vma; + unsigned long vma_end; + vma = find_vma(mm, aligned_start); + if (!vma || (aligned_start <= vma->vm_end)) { + /* Avoid getting stuck in an error condition */ + aligned_start += PAGE_SIZE; + continue; + } + vma_end = vma->vm_end; + if (vma->vm_flags & VM_EXEC) { + /* Executable */ + eaddr = aligned_start; + while (eaddr < vma_end) { + sh64_icache_inv_user_page(vma, eaddr); + eaddr += PAGE_SIZE; + } + } + aligned_start = vma->vm_end; /* Skip to start of next region */ + } + if (mm_asid != current_asid) { + switch_and_save_asid(current_asid); + local_irq_restore(flags); + } + } +} + +static void sh64_icache_inv_user_small_range(struct mm_struct *mm, + unsigned long start, int len) +{ + + /* Invalidate a small range of user context I-cache, not necessarily + page (or even cache-line) aligned. */ + + unsigned long long eaddr = start; + unsigned long long eaddr_end = start + len; + unsigned long current_asid, mm_asid; + unsigned long long flags; + unsigned long long epage_start; + + /* Since this is used inside ptrace, the ASID in the mm context + typically won't match current_asid. We'll have to switch ASID to do + this. For safety, and given that the range will be small, do all + this under cli. + + Note, there is a hazard that the ASID in mm->context is no longer + actually associated with mm, i.e. if the mm->context has started a + new cycle since mm was last active. However, this is just a + performance issue: all that happens is that we invalidate lines + belonging to another mm, so the owning process has to refill them + when that mm goes live again. mm itself can't have any cache + entries because there will have been a flush_cache_all when the new + mm->context cycle started. */ + + /* Align to start of cache line. Otherwise, suppose len==8 and start + was at 32N+28 : the last 4 bytes wouldn't get invalidated. */ + eaddr = start & L1_CACHE_ALIGN_MASK; + eaddr_end = start + len; + + local_irq_save(flags); + mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; + current_asid = switch_and_save_asid(mm_asid); + + epage_start = eaddr & PAGE_MASK; + + while (eaddr < eaddr_end) + { + asm __volatile__("icbi %0, 0" : : "r" (eaddr)); + eaddr += L1_CACHE_BYTES; + } + switch_and_save_asid(current_asid); + local_irq_restore(flags); +} + +static void sh64_icache_inv_current_user_range(unsigned long start, unsigned long end) +{ + /* The icbi instruction never raises ITLBMISS. i.e. if there's not a + cache hit on the virtual tag the instruction ends there, without a + TLB lookup. */ + + unsigned long long aligned_start; + unsigned long long ull_end; + unsigned long long addr; + + ull_end = end; + + /* Just invalidate over the range using the natural addresses. TLB + miss handling will be OK (TBC). Since it's for the current process, + either we're already in the right ASID context, or the ASIDs have + been recycled since we were last active in which case we might just + invalidate another processes I-cache entries : no worries, just a + performance drop for him. */ + aligned_start = start & L1_CACHE_ALIGN_MASK; + addr = aligned_start; + while (addr < ull_end) { + asm __volatile__ ("icbi %0, 0" : : "r" (addr)); + asm __volatile__ ("nop"); + asm __volatile__ ("nop"); + addr += L1_CACHE_BYTES; + } +} + +#endif /* !CONFIG_ICACHE_DISABLED */ + +/****************************************************************************/ + +#ifndef CONFIG_DCACHE_DISABLED + +/* Buffer used as the target of alloco instructions to purge data from cache + sets by natural eviction. -- RPC */ +#define DUMMY_ALLOCO_AREA_SIZE L1_CACHE_SIZE_BYTES + (1024 * 4) +static unsigned char dummy_alloco_area[DUMMY_ALLOCO_AREA_SIZE] __cacheline_aligned = { 0, }; + +/****************************************************************************/ + +static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets) +{ + /* Purge all ways in a particular block of sets, specified by the base + set number and number of sets. Can handle wrap-around, if that's + needed. */ + + int dummy_buffer_base_set; + unsigned long long eaddr, eaddr0, eaddr1; + int j; + int set_offset; + + dummy_buffer_base_set = ((int)&dummy_alloco_area & cpu_data->dcache.idx_mask) >> cpu_data->dcache.entry_shift; + set_offset = sets_to_purge_base - dummy_buffer_base_set; + + for (j=0; jdcache.sets - 1); + eaddr0 = (unsigned long long)dummy_alloco_area + (set_offset << cpu_data->dcache.entry_shift); + + /* Do one alloco which hits the required set per cache way. For + write-back mode, this will purge the #ways resident lines. There's + little point unrolling this loop because the allocos stall more if + they're too close together. */ + eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; + for (eaddr=eaddr0; eaddrdcache.way_ofs) { + asm __volatile__ ("alloco %0, 0" : : "r" (eaddr)); + asm __volatile__ ("synco"); /* TAKum03020 */ + } + + eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; + for (eaddr=eaddr0; eaddrdcache.way_ofs) { + /* Load from each address. Required because alloco is a NOP if + the cache is write-through. Write-through is a config option. */ + if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags))) + *(volatile unsigned char *)(int)eaddr; + } + } + + /* Don't use OCBI to invalidate the lines. That costs cycles directly. + If the dummy block is just left resident, it will naturally get + evicted as required. */ + + return; +} + +/****************************************************************************/ + +static void sh64_dcache_purge_all(void) +{ + /* Purge the entire contents of the dcache. The most efficient way to + achieve this is to use alloco instructions on a region of unused + memory equal in size to the cache, thereby causing the current + contents to be discarded by natural eviction. The alternative, + namely reading every tag, setting up a mapping for the corresponding + page and doing an OCBP for the line, would be much more expensive. + */ + + sh64_dcache_purge_sets(0, cpu_data->dcache.sets); + + return; + +} + +/****************************************************************************/ + +static void sh64_dcache_purge_kernel_range(unsigned long start, unsigned long end) +{ + /* Purge the range of addresses [start,end] from the D-cache. The + addresses lie in the superpage mapping. There's no harm if we + overpurge at either end - just a small performance loss. */ + unsigned long long ullend, addr, aligned_start; +#if (NEFF == 32) + aligned_start = (unsigned long long)(signed long long)(signed long) start; +#else +#error "NEFF != 32" +#endif + aligned_start &= L1_CACHE_ALIGN_MASK; + addr = aligned_start; +#if (NEFF == 32) + ullend = (unsigned long long) (signed long long) (signed long) end; +#else +#error "NEFF != 32" +#endif + while (addr <= ullend) { + asm __volatile__ ("ocbp %0, 0" : : "r" (addr)); + addr += L1_CACHE_BYTES; + } + return; +} + +/* Assumes this address (+ (2**n_synbits) pages up from it) aren't used for + anything else in the kernel */ +#define MAGIC_PAGE0_START 0xffffffffec000000ULL + +static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned long eaddr) +{ + /* Purge the physical page 'paddr' from the cache. It's known that any + cache lines requiring attention have the same page colour as the the + address 'eaddr'. + + This relies on the fact that the D-cache matches on physical tags + when no virtual tag matches. So we create an alias for the original + page and purge through that. (Alternatively, we could have done + this by switching ASID to match the original mapping and purged + through that, but that involves ASID switching cost + probably a + TLBMISS + refill anyway.) + */ + + unsigned long long magic_page_start; + unsigned long long magic_eaddr, magic_eaddr_end; + + magic_page_start = MAGIC_PAGE0_START + (eaddr & CACHE_OC_SYN_MASK); + + /* As long as the kernel is not pre-emptible, this doesn't need to be + under cli/sti. */ + + sh64_setup_dtlb_cache_slot(magic_page_start, get_asid(), paddr); + + magic_eaddr = magic_page_start; + magic_eaddr_end = magic_eaddr + PAGE_SIZE; + while (magic_eaddr < magic_eaddr_end) { + /* Little point in unrolling this loop - the OCBPs are blocking + and won't go any quicker (i.e. the loop overhead is parallel + to part of the OCBP execution.) */ + asm __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr)); + magic_eaddr += L1_CACHE_BYTES; + } + + sh64_teardown_dtlb_cache_slot(); +} + +/****************************************************************************/ + +static void sh64_dcache_purge_phy_page(unsigned long paddr) +{ + /* Pure a page given its physical start address, by creating a + temporary 1 page mapping and purging across that. Even if we know + the virtual address (& vma or mm) of the page, the method here is + more elegant because it avoids issues of coping with page faults on + the purge instructions (i.e. no special-case code required in the + critical path in the TLB miss handling). */ + + unsigned long long eaddr_start, eaddr, eaddr_end; + int i; + + /* As long as the kernel is not pre-emptible, this doesn't need to be + under cli/sti. */ + + eaddr_start = MAGIC_PAGE0_START; + for (i=0; i < (1 << CACHE_OC_N_SYNBITS); i++) { + sh64_setup_dtlb_cache_slot(eaddr_start, get_asid(), paddr); + + eaddr = eaddr_start; + eaddr_end = eaddr + PAGE_SIZE; + while (eaddr < eaddr_end) { + asm __volatile__ ("ocbp %0, 0" : : "r" (eaddr)); + eaddr += L1_CACHE_BYTES; + } + + sh64_teardown_dtlb_cache_slot(); + eaddr_start += PAGE_SIZE; + } +} + +static void sh64_dcache_purge_user_pages(struct mm_struct *mm, + unsigned long addr, unsigned long end) +{ + pgd_t *pgd; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + spinlock_t *ptl; + unsigned long paddr; + + if (!mm) + return; /* No way to find physical address of page */ + + pgd = pgd_offset(mm, addr); + if (pgd_bad(*pgd)) + return; + + pmd = pmd_offset(pgd, addr); + if (pmd_none(*pmd) || pmd_bad(*pmd)) + return; + + pte = pte_offset_map_lock(mm, pmd, addr, &ptl); + do { + entry = *pte; + if (pte_none(entry) || !pte_present(entry)) + continue; + paddr = pte_val(entry) & PAGE_MASK; + sh64_dcache_purge_coloured_phy_page(paddr, addr); + } while (pte++, addr += PAGE_SIZE, addr != end); + pte_unmap_unlock(pte - 1, ptl); +} +/****************************************************************************/ + +static void sh64_dcache_purge_user_range(struct mm_struct *mm, + unsigned long start, unsigned long end) +{ + /* There are at least 5 choices for the implementation of this, with + pros (+), cons(-), comments(*): + + 1. ocbp each line in the range through the original user's ASID + + no lines spuriously evicted + - tlbmiss handling (must either handle faults on demand => extra + special-case code in tlbmiss critical path), or map the page in + advance (=> flush_tlb_range in advance to avoid multiple hits) + - ASID switching + - expensive for large ranges + + 2. temporarily map each page in the range to a special effective + address and ocbp through the temporary mapping; relies on the + fact that SH-5 OCB* always do TLB lookup and match on ptags (they + never look at the etags) + + no spurious evictions + - expensive for large ranges + * surely cheaper than (1) + + 3. walk all the lines in the cache, check the tags, if a match + occurs create a page mapping to ocbp the line through + + no spurious evictions + - tag inspection overhead + - (especially for small ranges) + - potential cost of setting up/tearing down page mapping for + every line that matches the range + * cost partly independent of range size + + 4. walk all the lines in the cache, check the tags, if a match + occurs use 4 * alloco to purge the line (+3 other probably + innocent victims) by natural eviction + + no tlb mapping overheads + - spurious evictions + - tag inspection overhead + + 5. implement like flush_cache_all + + no tag inspection overhead + - spurious evictions + - bad for small ranges + + (1) can be ruled out as more expensive than (2). (2) appears best + for small ranges. The choice between (3), (4) and (5) for large + ranges and the range size for the large/small boundary need + benchmarking to determine. + + For now use approach (2) for small ranges and (5) for large ones. + + */ + + int n_pages; + + n_pages = ((end - start) >> PAGE_SHIFT); + if (n_pages >= 64 || ((start ^ (end - 1)) & PMD_MASK)) { +#if 1 + sh64_dcache_purge_all(); +#else + unsigned long long set, way; + unsigned long mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; + for (set = 0; set < cpu_data->dcache.sets; set++) { + unsigned long long set_base_config_addr = CACHE_OC_ADDRESS_ARRAY + (set << cpu_data->dcache.set_shift); + for (way = 0; way < cpu_data->dcache.ways; way++) { + unsigned long long config_addr = set_base_config_addr + (way << cpu_data->dcache.way_step_shift); + unsigned long long tag0; + unsigned long line_valid; + + asm __volatile__("getcfg %1, 0, %0" : "=r" (tag0) : "r" (config_addr)); + line_valid = tag0 & SH_CACHE_VALID; + if (line_valid) { + unsigned long cache_asid; + unsigned long epn; + + cache_asid = (tag0 & cpu_data->dcache.asid_mask) >> cpu_data->dcache.asid_shift; + /* The next line needs some + explanation. The virtual tags + encode bits [31:13] of the virtual + address, bit [12] of the 'tag' being + implied by the cache set index. */ + epn = (tag0 & cpu_data->dcache.epn_mask) | ((set & 0x80) << cpu_data->dcache.entry_shift); + + if ((cache_asid == mm_asid) && (start <= epn) && (epn < end)) { + /* TODO : could optimise this + call by batching multiple + adjacent sets together. */ + sh64_dcache_purge_sets(set, 1); + break; /* Don't waste time inspecting other ways for this set */ + } + } + } + } +#endif + } else { + /* Small range, covered by a single page table page */ + start &= PAGE_MASK; /* should already be so */ + end = PAGE_ALIGN(end); /* should already be so */ + sh64_dcache_purge_user_pages(mm, start, end); + } + return; +} + +static void sh64_dcache_wback_current_user_range(unsigned long start, unsigned long end) +{ + unsigned long long aligned_start; + unsigned long long ull_end; + unsigned long long addr; + + ull_end = end; + + /* Just wback over the range using the natural addresses. TLB miss + handling will be OK (TBC) : the range has just been written to by + the signal frame setup code, so the PTEs must exist. + + Note, if we have CONFIG_PREEMPT and get preempted inside this loop, + it doesn't matter, even if the pid->ASID mapping changes whilst + we're away. In that case the cache will have been flushed when the + mapping was renewed. So the writebacks below will be nugatory (and + we'll doubtless have to fault the TLB entry/ies in again with the + new ASID), but it's a rare case. + */ + aligned_start = start & L1_CACHE_ALIGN_MASK; + addr = aligned_start; + while (addr < ull_end) { + asm __volatile__ ("ocbwb %0, 0" : : "r" (addr)); + addr += L1_CACHE_BYTES; + } +} + +/****************************************************************************/ + +/* These *MUST* lie in an area of virtual address space that's otherwise unused. */ +#define UNIQUE_EADDR_START 0xe0000000UL +#define UNIQUE_EADDR_END 0xe8000000UL + +static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned long paddr) +{ + /* Given a physical address paddr, and a user virtual address + user_eaddr which will eventually be mapped to it, create a one-off + kernel-private eaddr mapped to the same paddr. This is used for + creating special destination pages for copy_user_page and + clear_user_page */ + + static unsigned long current_pointer = UNIQUE_EADDR_START; + unsigned long coloured_pointer; + + if (current_pointer == UNIQUE_EADDR_END) { + sh64_dcache_purge_all(); + current_pointer = UNIQUE_EADDR_START; + } + + coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) | (user_eaddr & CACHE_OC_SYN_MASK); + sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr); + + current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS); + + return coloured_pointer; +} + +/****************************************************************************/ + +static void sh64_copy_user_page_coloured(void *to, void *from, unsigned long address) +{ + void *coloured_to; + + /* Discard any existing cache entries of the wrong colour. These are + present quite often, if the kernel has recently used the page + internally, then given it up, then it's been allocated to the user. + */ + sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); + + coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); + sh64_page_copy(from, coloured_to); + + sh64_teardown_dtlb_cache_slot(); +} + +static void sh64_clear_user_page_coloured(void *to, unsigned long address) +{ + void *coloured_to; + + /* Discard any existing kernel-originated lines of the wrong colour (as + above) */ + sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); + + coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); + sh64_page_clear(coloured_to); + + sh64_teardown_dtlb_cache_slot(); +} + +#endif /* !CONFIG_DCACHE_DISABLED */ + +/****************************************************************************/ + +/*########################################################################## + EXTERNALLY CALLABLE API. + ##########################################################################*/ + +/* These functions are described in Documentation/cachetlb.txt. + Each one of these functions varies in behaviour depending on whether the + I-cache and/or D-cache are configured out. + + Note that the Linux term 'flush' corresponds to what is termed 'purge' in + the sh/sh64 jargon for the D-cache, i.e. write back dirty data then + invalidate the cache lines, and 'invalidate' for the I-cache. + */ + +#undef FLUSH_TRACE + +void flush_cache_all(void) +{ + /* Invalidate the entire contents of both caches, after writing back to + memory any dirty data from the D-cache. */ + sh64_dcache_purge_all(); + sh64_icache_inv_all(); +} + +/****************************************************************************/ + +void flush_cache_mm(struct mm_struct *mm) +{ + /* Invalidate an entire user-address space from both caches, after + writing back dirty data (e.g. for shared mmap etc). */ + + /* This could be coded selectively by inspecting all the tags then + doing 4*alloco on any set containing a match (as for + flush_cache_range), but fork/exit/execve (where this is called from) + are expensive anyway. */ + + /* Have to do a purge here, despite the comments re I-cache below. + There could be odd-coloured dirty data associated with the mm still + in the cache - if this gets written out through natural eviction + after the kernel has reused the page there will be chaos. + */ + + sh64_dcache_purge_all(); + + /* The mm being torn down won't ever be active again, so any Icache + lines tagged with its ASID won't be visible for the rest of the + lifetime of this ASID cycle. Before the ASID gets reused, there + will be a flush_cache_all. Hence we don't need to touch the + I-cache. This is similar to the lack of action needed in + flush_tlb_mm - see fault.c. */ +} + +/****************************************************************************/ + +void flush_cache_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + + /* Invalidate (from both caches) the range [start,end) of virtual + addresses from the user address space specified by mm, after writing + back any dirty data. + + Note, 'end' is 1 byte beyond the end of the range to flush. */ + + sh64_dcache_purge_user_range(mm, start, end); + sh64_icache_inv_user_page_range(mm, start, end); +} + +/****************************************************************************/ + +void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn) +{ + /* Invalidate any entries in either cache for the vma within the user + address space vma->vm_mm for the page starting at virtual address + 'eaddr'. This seems to be used primarily in breaking COW. Note, + the I-cache must be searched too in case the page in question is + both writable and being executed from (e.g. stack trampolines.) + + Note, this is called with pte lock held. + */ + + sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT); + + if (vma->vm_flags & VM_EXEC) { + sh64_icache_inv_user_page(vma, eaddr); + } +} + +/****************************************************************************/ + +#ifndef CONFIG_DCACHE_DISABLED + +void copy_user_page(void *to, void *from, unsigned long address, struct page *page) +{ + /* 'from' and 'to' are kernel virtual addresses (within the superpage + mapping of the physical RAM). 'address' is the user virtual address + where the copy 'to' will be mapped after. This allows a custom + mapping to be used to ensure that the new copy is placed in the + right cache sets for the user to see it without having to bounce it + out via memory. Note however : the call to flush_page_to_ram in + (generic)/mm/memory.c:(break_cow) undoes all this good work in that one + very important case! + + TBD : can we guarantee that on every call, any cache entries for + 'from' are in the same colour sets as 'address' also? i.e. is this + always used just to deal with COW? (I suspect not). */ + + /* There are two possibilities here for when the page 'from' was last accessed: + * by the kernel : this is OK, no purge required. + * by the/a user (e.g. for break_COW) : need to purge. + + If the potential user mapping at 'address' is the same colour as + 'from' there is no need to purge any cache lines from the 'from' + page mapped into cache sets of colour 'address'. (The copy will be + accessing the page through 'from'). + */ + + if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0) { + sh64_dcache_purge_coloured_phy_page(__pa(from), address); + } + + if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { + /* No synonym problem on destination */ + sh64_page_copy(from, to); + } else { + sh64_copy_user_page_coloured(to, from, address); + } + + /* Note, don't need to flush 'from' page from the cache again - it's + done anyway by the generic code */ +} + +void clear_user_page(void *to, unsigned long address, struct page *page) +{ + /* 'to' is a kernel virtual address (within the superpage + mapping of the physical RAM). 'address' is the user virtual address + where the 'to' page will be mapped after. This allows a custom + mapping to be used to ensure that the new copy is placed in the + right cache sets for the user to see it without having to bounce it + out via memory. + */ + + if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { + /* No synonym problem on destination */ + sh64_page_clear(to); + } else { + sh64_clear_user_page_coloured(to, address); + } +} + +#endif /* !CONFIG_DCACHE_DISABLED */ + +/****************************************************************************/ + +void flush_dcache_page(struct page *page) +{ + sh64_dcache_purge_phy_page(page_to_phys(page)); + wmb(); +} + +/****************************************************************************/ + +void flush_icache_range(unsigned long start, unsigned long end) +{ + /* Flush the range [start,end] of kernel virtual adddress space from + the I-cache. The corresponding range must be purged from the + D-cache also because the SH-5 doesn't have cache snooping between + the caches. The addresses will be visible through the superpage + mapping, therefore it's guaranteed that there no cache entries for + the range in cache sets of the wrong colour. + + Primarily used for cohering the I-cache after a module has + been loaded. */ + + /* We also make sure to purge the same range from the D-cache since + flush_page_to_ram() won't be doing this for us! */ + + sh64_dcache_purge_kernel_range(start, end); + wmb(); + sh64_icache_inv_kernel_range(start, end); +} + +/****************************************************************************/ + +void flush_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long addr, int len) +{ + /* Flush the range of user (defined by vma->vm_mm) address space + starting at 'addr' for 'len' bytes from the cache. The range does + not straddle a page boundary, the unique physical page containing + the range is 'page'. This seems to be used mainly for invalidating + an address range following a poke into the program text through the + ptrace() call from another process (e.g. for BRK instruction + insertion). */ + + sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr); + mb(); + + if (vma->vm_flags & VM_EXEC) { + sh64_icache_inv_user_small_range(vma->vm_mm, addr, len); + } +} + +/*########################################################################## + ARCH/SH64 PRIVATE CALLABLE API. + ##########################################################################*/ + +void flush_cache_sigtramp(unsigned long start, unsigned long end) +{ + /* For the address range [start,end), write back the data from the + D-cache and invalidate the corresponding region of the I-cache for + the current process. Used to flush signal trampolines on the stack + to make them executable. */ + + sh64_dcache_wback_current_user_range(start, end); + wmb(); + sh64_icache_inv_current_user_range(start, end); +} + diff -puN arch/sh/mm/cache-sh7705.c~git-sh arch/sh/mm/cache-sh7705.c --- a/arch/sh/mm/cache-sh7705.c~git-sh +++ a/arch/sh/mm/cache-sh7705.c @@ -71,7 +71,7 @@ void flush_icache_range(unsigned long st /* * Writeback&Invalidate the D-cache of the page */ -static void __flush_dcache_page(unsigned long phys) +static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys) { unsigned long ways, waysize, addrstart; unsigned long flags; @@ -92,7 +92,7 @@ static void __flush_dcache_page(unsigned * possible. */ local_irq_save(flags); - jump_to_P2(); + jump_to_uncached(); ways = current_cpu_data.dcache.ways; waysize = current_cpu_data.dcache.sets; @@ -118,7 +118,7 @@ static void __flush_dcache_page(unsigned addrstart += current_cpu_data.dcache.way_incr; } while (--ways); - back_to_P1(); + back_to_cached(); local_irq_restore(flags); } @@ -132,15 +132,15 @@ void flush_dcache_page(struct page *page __flush_dcache_page(PHYSADDR(page_address(page))); } -void flush_cache_all(void) +void __uses_jump_to_uncached flush_cache_all(void) { unsigned long flags; local_irq_save(flags); - jump_to_P2(); + jump_to_uncached(); cache_wback_all(); - back_to_P1(); + back_to_cached(); local_irq_restore(flags); } diff -puN arch/sh/mm/clear_page.S~git-sh /dev/null --- a/arch/sh/mm/clear_page.S +++ /dev/null @@ -1,152 +0,0 @@ -/* - * __clear_user_page, __clear_user, clear_page implementation of SuperH - * - * Copyright (C) 2001 Kaz Kojima - * Copyright (C) 2001, 2002 Niibe Yutaka - * Copyright (C) 2006 Paul Mundt - */ -#include -#include - -/* - * clear_page_slow - * @to: P1 address - * - * void clear_page_slow(void *to) - */ - -/* - * r0 --- scratch - * r4 --- to - * r5 --- to + PAGE_SIZE - */ -ENTRY(clear_page_slow) - mov r4,r5 - mov.l .Llimit,r0 - add r0,r5 - mov #0,r0 - ! -1: -#if defined(CONFIG_CPU_SH3) - mov.l r0,@r4 -#elif defined(CONFIG_CPU_SH4) - movca.l r0,@r4 - mov r4,r1 -#endif - add #32,r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 - mov.l r0,@-r4 -#if defined(CONFIG_CPU_SH4) - ocbwb @r1 -#endif - cmp/eq r5,r4 - bf/s 1b - add #28,r4 - ! - rts - nop -.Llimit: .long (PAGE_SIZE-28) - -ENTRY(__clear_user) - ! - mov #0, r0 - mov #0xe0, r1 ! 0xffffffe0 - ! - ! r4..(r4+31)&~32 -------- not aligned [ Area 0 ] - ! (r4+31)&~32..(r4+r5)&~32 -------- aligned [ Area 1 ] - ! (r4+r5)&~32..r4+r5 -------- not aligned [ Area 2 ] - ! - ! Clear area 0 - mov r4, r2 - ! - tst r1, r5 ! length < 32 - bt .Larea2 ! skip to remainder - ! - add #31, r2 - and r1, r2 - cmp/eq r4, r2 - bt .Larea1 - mov r2, r3 - sub r4, r3 - mov r3, r7 - mov r4, r2 - ! -.L0: dt r3 -0: mov.b r0, @r2 - bf/s .L0 - add #1, r2 - ! - sub r7, r5 - mov r2, r4 -.Larea1: - mov r4, r3 - add r5, r3 - and r1, r3 - cmp/hi r2, r3 - bf .Larea2 - ! - ! Clear area 1 -#if defined(CONFIG_CPU_SH4) -1: movca.l r0, @r2 -#else -1: mov.l r0, @r2 -#endif - add #4, r2 -2: mov.l r0, @r2 - add #4, r2 -3: mov.l r0, @r2 - add #4, r2 -4: mov.l r0, @r2 - add #4, r2 -5: mov.l r0, @r2 - add #4, r2 -6: mov.l r0, @r2 - add #4, r2 -7: mov.l r0, @r2 - add #4, r2 -8: mov.l r0, @r2 - add #4, r2 - cmp/hi r2, r3 - bt/s 1b - nop - ! - ! Clear area 2 -.Larea2: - mov r4, r3 - add r5, r3 - cmp/hs r3, r2 - bt/s .Ldone - sub r2, r3 -.L2: dt r3 -9: mov.b r0, @r2 - bf/s .L2 - add #1, r2 - ! -.Ldone: rts - mov #0, r0 ! return 0 as normal return - - ! return the number of bytes remained -.Lbad_clear_user: - mov r4, r0 - add r5, r0 - rts - sub r2, r0 - -.section __ex_table,"a" - .align 2 - .long 0b, .Lbad_clear_user - .long 1b, .Lbad_clear_user - .long 2b, .Lbad_clear_user - .long 3b, .Lbad_clear_user - .long 4b, .Lbad_clear_user - .long 5b, .Lbad_clear_user - .long 6b, .Lbad_clear_user - .long 7b, .Lbad_clear_user - .long 8b, .Lbad_clear_user - .long 9b, .Lbad_clear_user -.previous diff -puN arch/sh/mm/consistent.c~git-sh arch/sh/mm/consistent.c --- a/arch/sh/mm/consistent.c~git-sh +++ a/arch/sh/mm/consistent.c @@ -1,7 +1,7 @@ /* * arch/sh/mm/consistent.c * - * Copyright (C) 2004 Paul Mundt + * Copyright (C) 2004 - 2007 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -16,7 +16,7 @@ void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle) { struct page *page, *end, *free; - void *ret; + void *ret, *vp; int order; size = PAGE_ALIGN(size); @@ -28,13 +28,20 @@ void *consistent_alloc(gfp_t gfp, size_t split_page(page, order); ret = page_address(page); - memset(ret, 0, size); *handle = virt_to_phys(ret); + vp = ioremap_nocache(*handle, size); + if (!vp) { + free_pages((unsigned long)ret, order); + return NULL; + } + + memset(vp, 0, size); + /* * We must flush the cache before we pass it on to the device */ - __flush_purge_region(ret, size); + dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL); page = virt_to_page(ret); free = page + (size >> PAGE_SHIFT); @@ -47,24 +54,31 @@ void *consistent_alloc(gfp_t gfp, size_t } } - return P2SEGADDR(ret); + return vp; } +EXPORT_SYMBOL(consistent_alloc); -void consistent_free(void *vaddr, size_t size) +void consistent_free(void *vaddr, size_t size, dma_addr_t dma_handle) { - unsigned long addr = P1SEGADDR((unsigned long)vaddr); - struct page *page=virt_to_page(addr); - int num_pages=(size+PAGE_SIZE-1) >> PAGE_SHIFT; - int i; + struct page *page; + unsigned long addr; - for(i=0;i -#include - -/* - * copy_page_slow - * @to: P1 address - * @from: P1 address - * - * void copy_page_slow(void *to, void *from) - */ - -/* - * r0, r1, r2, r3, r4, r5, r6, r7 --- scratch - * r8 --- from + PAGE_SIZE - * r9 --- not used - * r10 --- to - * r11 --- from - */ -ENTRY(copy_page_slow) - mov.l r8,@-r15 - mov.l r10,@-r15 - mov.l r11,@-r15 - mov r4,r10 - mov r5,r11 - mov r5,r8 - mov.l .Lpsz,r0 - add r0,r8 - ! -1: mov.l @r11+,r0 - mov.l @r11+,r1 - mov.l @r11+,r2 - mov.l @r11+,r3 - mov.l @r11+,r4 - mov.l @r11+,r5 - mov.l @r11+,r6 - mov.l @r11+,r7 -#if defined(CONFIG_CPU_SH3) - mov.l r0,@r10 -#elif defined(CONFIG_CPU_SH4) - movca.l r0,@r10 - mov r10,r0 -#endif - add #32,r10 - mov.l r7,@-r10 - mov.l r6,@-r10 - mov.l r5,@-r10 - mov.l r4,@-r10 - mov.l r3,@-r10 - mov.l r2,@-r10 - mov.l r1,@-r10 -#if defined(CONFIG_CPU_SH4) - ocbwb @r0 -#endif - cmp/eq r11,r8 - bf/s 1b - add #28,r10 - ! - mov.l @r15+,r11 - mov.l @r15+,r10 - mov.l @r15+,r8 - rts - nop - - .align 2 -.Lpsz: .long PAGE_SIZE -/* - * __kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); - * Return the number of bytes NOT copied - */ -#define EX(...) \ - 9999: __VA_ARGS__ ; \ - .section __ex_table, "a"; \ - .long 9999b, 6000f ; \ - .previous -ENTRY(__copy_user) - ! Check if small number of bytes - mov #11,r0 - mov r4,r3 - cmp/gt r0,r6 ! r6 (len) > r0 (11) - bf/s .L_cleanup_loop_no_pop - add r6,r3 ! last destination address - - ! Calculate bytes needed to align to src - mov.l r11,@-r15 - neg r5,r0 - mov.l r10,@-r15 - add #4,r0 - mov.l r9,@-r15 - and #3,r0 - mov.l r8,@-r15 - tst r0,r0 - bt 2f - -1: - ! Copy bytes to long word align src -EX( mov.b @r5+,r1 ) - dt r0 - add #-1,r6 -EX( mov.b r1,@r4 ) - bf/s 1b - add #1,r4 - - ! Jump to appropriate routine depending on dest -2: mov #3,r1 - mov r6, r2 - and r4,r1 - shlr2 r2 - shll2 r1 - mova .L_jump_tbl,r0 - mov.l @(r0,r1),r1 - jmp @r1 - nop - - .align 2 -.L_jump_tbl: - .long .L_dest00 - .long .L_dest01 - .long .L_dest10 - .long .L_dest11 - -/* - * Come here if there are less than 12 bytes to copy - * - * Keep the branch target close, so the bf/s callee doesn't overflow - * and result in a more expensive branch being inserted. This is the - * fast-path for small copies, the jump via the jump table will hit the - * default slow-path cleanup. -PFM. - */ -.L_cleanup_loop_no_pop: - tst r6,r6 ! Check explicitly for zero - bt 1f - -2: -EX( mov.b @r5+,r0 ) - dt r6 -EX( mov.b r0,@r4 ) - bf/s 2b - add #1,r4 - -1: mov #0,r0 ! normal return -5000: - -# Exception handler: -.section .fixup, "ax" -6000: - mov.l 8000f,r1 - mov r3,r0 - jmp @r1 - sub r4,r0 - .align 2 -8000: .long 5000b - -.previous - rts - nop - -! Destination = 00 - -.L_dest00: - ! Skip the large copy for small transfers - mov #(32+32-4), r0 - cmp/gt r6, r0 ! r0 (60) > r6 (len) - bt 1f - - ! Align dest to a 32 byte boundary - neg r4,r0 - add #0x20, r0 - and #0x1f, r0 - tst r0, r0 - bt 2f - - sub r0, r6 - shlr2 r0 -3: -EX( mov.l @r5+,r1 ) - dt r0 -EX( mov.l r1,@r4 ) - bf/s 3b - add #4,r4 - -2: -EX( mov.l @r5+,r0 ) -EX( mov.l @r5+,r1 ) -EX( mov.l @r5+,r2 ) -EX( mov.l @r5+,r7 ) -EX( mov.l @r5+,r8 ) -EX( mov.l @r5+,r9 ) -EX( mov.l @r5+,r10 ) -EX( mov.l @r5+,r11 ) -#ifdef CONFIG_CPU_SH4 -EX( movca.l r0,@r4 ) -#else -EX( mov.l r0,@r4 ) -#endif - add #-32, r6 -EX( mov.l r1,@(4,r4) ) - mov #32, r0 -EX( mov.l r2,@(8,r4) ) - cmp/gt r6, r0 ! r0 (32) > r6 (len) -EX( mov.l r7,@(12,r4) ) -EX( mov.l r8,@(16,r4) ) -EX( mov.l r9,@(20,r4) ) -EX( mov.l r10,@(24,r4) ) -EX( mov.l r11,@(28,r4) ) - bf/s 2b - add #32,r4 - -1: mov r6, r0 - shlr2 r0 - tst r0, r0 - bt .L_cleanup -1: -EX( mov.l @r5+,r1 ) - dt r0 -EX( mov.l r1,@r4 ) - bf/s 1b - add #4,r4 - - bra .L_cleanup - nop - -! Destination = 10 - -.L_dest10: - mov r2,r7 - shlr2 r7 - shlr r7 - tst r7,r7 - mov #7,r0 - bt/s 1f - and r0,r2 -2: - dt r7 -#ifdef CONFIG_CPU_LITTLE_ENDIAN -EX( mov.l @r5+,r0 ) -EX( mov.l @r5+,r1 ) -EX( mov.l @r5+,r8 ) -EX( mov.l @r5+,r9 ) -EX( mov.l @r5+,r10 ) -EX( mov.w r0,@r4 ) - add #2,r4 - xtrct r1,r0 - xtrct r8,r1 - xtrct r9,r8 - xtrct r10,r9 - -EX( mov.l r0,@r4 ) -EX( mov.l r1,@(4,r4) ) -EX( mov.l r8,@(8,r4) ) -EX( mov.l r9,@(12,r4) ) - -EX( mov.l @r5+,r1 ) -EX( mov.l @r5+,r8 ) -EX( mov.l @r5+,r0 ) - xtrct r1,r10 - xtrct r8,r1 - xtrct r0,r8 - shlr16 r0 -EX( mov.l r10,@(16,r4) ) -EX( mov.l r1,@(20,r4) ) -EX( mov.l r8,@(24,r4) ) -EX( mov.w r0,@(28,r4) ) - bf/s 2b - add #30,r4 -#else -EX( mov.l @(28,r5),r0 ) -EX( mov.l @(24,r5),r8 ) -EX( mov.l @(20,r5),r9 ) -EX( mov.l @(16,r5),r10 ) -EX( mov.w r0,@(30,r4) ) - add #-2,r4 - xtrct r8,r0 - xtrct r9,r8 - xtrct r10,r9 -EX( mov.l r0,@(28,r4) ) -EX( mov.l r8,@(24,r4) ) -EX( mov.l r9,@(20,r4) ) - -EX( mov.l @(12,r5),r0 ) -EX( mov.l @(8,r5),r8 ) - xtrct r0,r10 -EX( mov.l @(4,r5),r9 ) - mov.l r10,@(16,r4) -EX( mov.l @r5,r10 ) - xtrct r8,r0 - xtrct r9,r8 - xtrct r10,r9 -EX( mov.l r0,@(12,r4) ) -EX( mov.l r8,@(8,r4) ) - swap.w r10,r0 -EX( mov.l r9,@(4,r4) ) -EX( mov.w r0,@(2,r4) ) - - add #32,r5 - bf/s 2b - add #34,r4 -#endif - tst r2,r2 - bt .L_cleanup - -1: ! Read longword, write two words per iteration -EX( mov.l @r5+,r0 ) - dt r2 -#ifdef CONFIG_CPU_LITTLE_ENDIAN -EX( mov.w r0,@r4 ) - shlr16 r0 -EX( mov.w r0,@(2,r4) ) -#else -EX( mov.w r0,@(2,r4) ) - shlr16 r0 -EX( mov.w r0,@r4 ) -#endif - bf/s 1b - add #4,r4 - - bra .L_cleanup - nop - -! Destination = 01 or 11 - -.L_dest01: -.L_dest11: - ! Read longword, write byte, word, byte per iteration -EX( mov.l @r5+,r0 ) - dt r2 -#ifdef CONFIG_CPU_LITTLE_ENDIAN -EX( mov.b r0,@r4 ) - shlr8 r0 - add #1,r4 -EX( mov.w r0,@r4 ) - shlr16 r0 -EX( mov.b r0,@(2,r4) ) - bf/s .L_dest01 - add #3,r4 -#else -EX( mov.b r0,@(3,r4) ) - shlr8 r0 - swap.w r0,r7 -EX( mov.b r7,@r4 ) - add #1,r4 -EX( mov.w r0,@r4 ) - bf/s .L_dest01 - add #3,r4 -#endif - -! Cleanup last few bytes -.L_cleanup: - mov r6,r0 - and #3,r0 - tst r0,r0 - bt .L_exit - mov r0,r6 - -.L_cleanup_loop: -EX( mov.b @r5+,r0 ) - dt r6 -EX( mov.b r0,@r4 ) - bf/s .L_cleanup_loop - add #1,r4 - -.L_exit: - mov #0,r0 ! normal return - -5000: - -# Exception handler: -.section .fixup, "ax" -6000: - mov.l 8000f,r1 - mov r3,r0 - jmp @r1 - sub r4,r0 - .align 2 -8000: .long 5000b - -.previous - mov.l @r15+,r8 - mov.l @r15+,r9 - mov.l @r15+,r10 - rts - mov.l @r15+,r11 diff -puN arch/sh/mm/extable.c~git-sh /dev/null --- a/arch/sh/mm/extable.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * linux/arch/sh/mm/extable.c - * Taken from: - * linux/arch/i386/mm/extable.c - */ - -#include -#include - -int fixup_exception(struct pt_regs *regs) -{ - const struct exception_table_entry *fixup; - - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return 1; - } - - return 0; -} diff -puN /dev/null arch/sh/mm/extable_32.c --- /dev/null +++ a/arch/sh/mm/extable_32.c @@ -0,0 +1,21 @@ +/* + * linux/arch/sh/mm/extable.c + * Taken from: + * linux/arch/i386/mm/extable.c + */ + +#include +#include + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return 1; + } + + return 0; +} diff -puN /dev/null arch/sh/mm/extable_64.c --- /dev/null +++ a/arch/sh/mm/extable_64.c @@ -0,0 +1,82 @@ +/* + * arch/sh/mm/extable_64.c + * + * Copyright (C) 2003 Richard Curnow + * Copyright (C) 2003, 2004 Paul Mundt + * + * Cloned from the 2.5 SH version.. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +extern unsigned long copy_user_memcpy, copy_user_memcpy_end; +extern void __copy_user_fixup(void); + +static const struct exception_table_entry __copy_user_fixup_ex = { + .fixup = (unsigned long)&__copy_user_fixup, +}; + +/* + * Some functions that may trap due to a bad user-mode address have too + * many loads and stores in them to make it at all practical to label + * each one and put them all in the main exception table. + * + * In particular, the fast memcpy routine is like this. It's fix-up is + * just to fall back to a slow byte-at-a-time copy, which is handled the + * conventional way. So it's functionally OK to just handle any trap + * occurring in the fast memcpy with that fixup. + */ +static const struct exception_table_entry *check_exception_ranges(unsigned long addr) +{ + if ((addr >= (unsigned long)©_user_memcpy) && + (addr <= (unsigned long)©_user_memcpy_end)) + return &__copy_user_fixup_ex; + + return NULL; +} + +/* Simple binary search */ +const struct exception_table_entry * +search_extable(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + const struct exception_table_entry *mid; + + mid = check_exception_ranges(value); + if (mid) + return mid; + + while (first <= last) { + long diff; + + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } + + return NULL; +} + +int fixup_exception(struct pt_regs *regs) +{ + const struct exception_table_entry *fixup; + + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return 1; + } + + return 0; +} diff -puN arch/sh/mm/fault.c~git-sh /dev/null --- a/arch/sh/mm/fault.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Page fault handler for SH with an MMU. - * - * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 - 2007 Paul Mundt - * - * Based on linux/arch/i386/mm/fault.c: - * Copyright (C) 1995 Linus Torvalds - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, - unsigned long writeaccess, - unsigned long address) -{ - struct task_struct *tsk; - struct mm_struct *mm; - struct vm_area_struct * vma; - int si_code; - int fault; - siginfo_t info; - - trace_hardirqs_on(); - local_irq_enable(); - -#ifdef CONFIG_SH_KGDB - if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); -#endif - - tsk = current; - mm = tsk->mm; - si_code = SEGV_MAPERR; - - if (unlikely(address >= TASK_SIZE)) { - /* - * Synchronize this task's top level page-table - * with the 'reference' page table. - * - * Do _not_ use "tsk" here. We might be inside - * an interrupt in the middle of a task switch.. - */ - int offset = pgd_index(address); - pgd_t *pgd, *pgd_k; - pud_t *pud, *pud_k; - pmd_t *pmd, *pmd_k; - - pgd = get_TTB() + offset; - pgd_k = swapper_pg_dir + offset; - - /* This will never happen with the folded page table. */ - if (!pgd_present(*pgd)) { - if (!pgd_present(*pgd_k)) - goto bad_area_nosemaphore; - set_pgd(pgd, *pgd_k); - return; - } - - pud = pud_offset(pgd, address); - pud_k = pud_offset(pgd_k, address); - if (pud_present(*pud) || !pud_present(*pud_k)) - goto bad_area_nosemaphore; - set_pud(pud, *pud_k); - - pmd = pmd_offset(pud, address); - pmd_k = pmd_offset(pud_k, address); - if (pmd_present(*pmd) || !pmd_present(*pmd_k)) - goto bad_area_nosemaphore; - set_pmd(pmd, *pmd_k); - - return; - } - - /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ - if (in_atomic() || !mm) - goto no_context; - - down_read(&mm->mmap_sem); - - vma = find_vma(mm, address); - if (!vma) - goto bad_area; - if (vma->vm_start <= address) - goto good_area; - if (!(vma->vm_flags & VM_GROWSDOWN)) - goto bad_area; - if (expand_stack(vma, address)) - goto bad_area; -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - si_code = SEGV_ACCERR; - if (writeaccess) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) - goto bad_area; - } - - /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. - */ -survive: - fault = handle_mm_fault(mm, vma, address, writeaccess); - 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) - tsk->maj_flt++; - else - tsk->min_flt++; - - up_read(&mm->mmap_sem); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: - up_read(&mm->mmap_sem); - -bad_area_nosemaphore: - if (user_mode(regs)) { - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = si_code; - info.si_addr = (void *) address; - force_sig_info(SIGSEGV, &info, tsk); - return; - } - -no_context: - /* Are we prepared to handle this kernel fault? */ - if (fixup_exception(regs)) - return; - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - * - */ - - bust_spinlocks(1); - - if (oops_may_print()) { - __typeof__(pte_val(__pte(0))) page; - - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL " - "pointer dereference"); - else - printk(KERN_ALERT "Unable to handle kernel paging " - "request"); - printk(" at virtual address %08lx\n", address); - printk(KERN_ALERT "pc = %08lx\n", regs->pc); - page = (unsigned long)get_TTB(); - if (page) { - page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT]; - printk(KERN_ALERT "*pde = %08lx\n", page); - if (page & _PAGE_PRESENT) { - page &= PAGE_MASK; - address &= 0x003ff000; - page = ((__typeof__(page) *) - __va(page))[address >> - PAGE_SHIFT]; - printk(KERN_ALERT "*pte = %08lx\n", page); - } - } - } - - die("Oops", regs, writeaccess); - bust_spinlocks(0); - do_exit(SIGKILL); - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -out_of_memory: - up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; - -do_sigbus: - up_read(&mm->mmap_sem); - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - info.si_signo = SIGBUS; - info.si_errno = 0; - info.si_code = BUS_ADRERR; - info.si_addr = (void *)address; - force_sig_info(SIGBUS, &info, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; -} - -#ifdef CONFIG_SH_STORE_QUEUES -/* - * This is a special case for the SH-4 store queues, as pages for this - * space still need to be faulted in before it's possible to flush the - * store queue cache for writeout to the remapped region. - */ -#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000) -#else -#define P3_ADDR_MAX P4SEG -#endif - -/* - * Called with interrupts disabled. - */ -asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, - unsigned long writeaccess, - unsigned long address) -{ - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - -#ifdef CONFIG_SH_KGDB - if (kgdb_nofault && kgdb_bus_err_hook) - kgdb_bus_err_hook(); -#endif - - /* - * We don't take page faults for P1, P2, and parts of P4, these - * are always mapped, whether it be due to legacy behaviour in - * 29-bit mode, or due to PMB configuration in 32-bit mode. - */ - if (address >= P3SEG && address < P3_ADDR_MAX) { - pgd = pgd_offset_k(address); - } else { - if (unlikely(address >= TASK_SIZE || !current->mm)) - return 1; - - pgd = pgd_offset(current->mm, address); - } - - pud = pud_offset(pgd, address); - if (pud_none_or_clear_bad(pud)) - return 1; - pmd = pmd_offset(pud, address); - if (pmd_none_or_clear_bad(pmd)) - return 1; - - pte = pte_offset_kernel(pmd, address); - entry = *pte; - if (unlikely(pte_none(entry) || pte_not_present(entry))) - return 1; - if (unlikely(writeaccess && !pte_write(entry))) - return 1; - - if (writeaccess) - entry = pte_mkdirty(entry); - entry = pte_mkyoung(entry); - - set_pte(pte, entry); - update_mmu_cache(NULL, address, entry); - - return 0; -} diff -puN /dev/null arch/sh/mm/fault_32.c --- /dev/null +++ a/arch/sh/mm/fault_32.c @@ -0,0 +1,303 @@ +/* + * Page fault handler for SH with an MMU. + * + * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2003 - 2007 Paul Mundt + * + * Based on linux/arch/i386/mm/fault.c: + * Copyright (C) 1995 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void __kprobes do_page_fault(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct * vma; + int si_code; + int fault; + siginfo_t info; + + trace_hardirqs_on(); + local_irq_enable(); + +#ifdef CONFIG_SH_KGDB + if (kgdb_nofault && kgdb_bus_err_hook) + kgdb_bus_err_hook(); +#endif + + tsk = current; + mm = tsk->mm; + si_code = SEGV_MAPERR; + + if (unlikely(address >= TASK_SIZE)) { + /* + * Synchronize this task's top level page-table + * with the 'reference' page table. + * + * Do _not_ use "tsk" here. We might be inside + * an interrupt in the middle of a task switch.. + */ + int offset = pgd_index(address); + pgd_t *pgd, *pgd_k; + pud_t *pud, *pud_k; + pmd_t *pmd, *pmd_k; + + pgd = get_TTB() + offset; + pgd_k = swapper_pg_dir + offset; + + /* This will never happen with the folded page table. */ + if (!pgd_present(*pgd)) { + if (!pgd_present(*pgd_k)) + goto bad_area_nosemaphore; + set_pgd(pgd, *pgd_k); + return; + } + + pud = pud_offset(pgd, address); + pud_k = pud_offset(pgd_k, address); + if (pud_present(*pud) || !pud_present(*pud_k)) + goto bad_area_nosemaphore; + set_pud(pud, *pud_k); + + pmd = pmd_offset(pud, address); + pmd_k = pmd_offset(pud_k, address); + if (pmd_present(*pmd) || !pmd_present(*pmd_k)) + goto bad_area_nosemaphore; + set_pmd(pmd, *pmd_k); + + return; + } + + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_atomic() || !mm) + goto no_context; + + down_read(&mm->mmap_sem); + + vma = find_vma(mm, address); + if (!vma) + goto bad_area; + if (vma->vm_start <= address) + goto good_area; + if (!(vma->vm_flags & VM_GROWSDOWN)) + goto bad_area; + if (expand_stack(vma, address)) + goto bad_area; +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + si_code = SEGV_ACCERR; + if (writeaccess) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) + goto bad_area; + } + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ +survive: + fault = handle_mm_fault(mm, vma, address, writeaccess); + 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) + tsk->maj_flt++; + else + tsk->min_flt++; + + up_read(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: + up_read(&mm->mmap_sem); + +bad_area_nosemaphore: + if (user_mode(regs)) { + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_code = si_code; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); + return; + } + +no_context: + /* Are we prepared to handle this kernel fault? */ + if (fixup_exception(regs)) + return; + +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + * + */ + + bust_spinlocks(1); + + if (oops_may_print()) { + __typeof__(pte_val(__pte(0))) page; + + if (address < PAGE_SIZE) + printk(KERN_ALERT "Unable to handle kernel NULL " + "pointer dereference"); + else + printk(KERN_ALERT "Unable to handle kernel paging " + "request"); + printk(" at virtual address %08lx\n", address); + printk(KERN_ALERT "pc = %08lx\n", regs->pc); + page = (unsigned long)get_TTB(); + if (page) { + page = ((__typeof__(page) *)page)[address >> PGDIR_SHIFT]; + printk(KERN_ALERT "*pde = %08lx\n", page); + if (page & _PAGE_PRESENT) { + page &= PAGE_MASK; + address &= 0x003ff000; + page = ((__typeof__(page) *) + __va(page))[address >> + PAGE_SHIFT]; + printk(KERN_ALERT "*pte = %08lx\n", page); + } + } + } + + die("Oops", regs, writeaccess); + bust_spinlocks(0); + do_exit(SIGKILL); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + up_read(&mm->mmap_sem); + if (is_global_init(current)) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", tsk->comm); + if (user_mode(regs)) + do_group_exit(SIGKILL); + goto no_context; + +do_sigbus: + up_read(&mm->mmap_sem); + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + info.si_signo = SIGBUS; + info.si_errno = 0; + info.si_code = BUS_ADRERR; + info.si_addr = (void *)address; + force_sig_info(SIGBUS, &info, tsk); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; +} + +#ifdef CONFIG_SH_STORE_QUEUES +/* + * This is a special case for the SH-4 store queues, as pages for this + * space still need to be faulted in before it's possible to flush the + * store queue cache for writeout to the remapped region. + */ +#define P3_ADDR_MAX (P4SEG_STORE_QUE + 0x04000000) +#else +#define P3_ADDR_MAX P4SEG +#endif + +/* + * Called with interrupts disabled. + */ +asmlinkage int __kprobes __do_page_fault(struct pt_regs *regs, + unsigned long writeaccess, + unsigned long address) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + +#ifdef CONFIG_SH_KGDB + if (kgdb_nofault && kgdb_bus_err_hook) + kgdb_bus_err_hook(); +#endif + + /* + * We don't take page faults for P1, P2, and parts of P4, these + * are always mapped, whether it be due to legacy behaviour in + * 29-bit mode, or due to PMB configuration in 32-bit mode. + */ + if (address >= P3SEG && address < P3_ADDR_MAX) { + pgd = pgd_offset_k(address); + } else { + if (unlikely(address >= TASK_SIZE || !current->mm)) + return 1; + + pgd = pgd_offset(current->mm, address); + } + + pud = pud_offset(pgd, address); + if (pud_none_or_clear_bad(pud)) + return 1; + pmd = pmd_offset(pud, address); + if (pmd_none_or_clear_bad(pmd)) + return 1; + + pte = pte_offset_kernel(pmd, address); + entry = *pte; + if (unlikely(pte_none(entry) || pte_not_present(entry))) + return 1; + if (unlikely(writeaccess && !pte_write(entry))) + return 1; + + if (writeaccess) + entry = pte_mkdirty(entry); + entry = pte_mkyoung(entry); + + set_pte(pte, entry); + update_mmu_cache(NULL, address, entry); + + return 0; +} diff -puN /dev/null arch/sh/mm/fault_64.c --- /dev/null +++ a/arch/sh/mm/fault_64.c @@ -0,0 +1,275 @@ +/* + * The SH64 TLB miss. + * + * Original code from fault.c + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * Fast PTE->TLB refill path + * Copyright (C) 2003 Richard.Curnow@superh.com + * + * IMPORTANT NOTES : + * The do_fast_page_fault function is called from a context in entry.S + * where very few registers have been saved. In particular, the code in + * this file must be compiled not to use ANY caller-save registers that + * are not part of the restricted save set. Also, it means that code in + * this file must not make calls to functions elsewhere in the kernel, or + * else the excepting context will see corruption in its caller-save + * registers. Plus, the entry.S save area is non-reentrant, so this code + * has to run with SR.BL==1, i.e. no interrupts taken inside it and panic + * on any exception. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Callable from fault.c, so not static */ +inline void __do_tlb_refill(unsigned long address, + unsigned long long is_text_not_data, pte_t *pte) +{ + unsigned long long ptel; + unsigned long long pteh=0; + struct tlb_info *tlbp; + unsigned long long next; + + /* Get PTEL first */ + ptel = pte_val(*pte); + + /* + * Set PTEH register + */ + pteh = address & MMU_VPN_MASK; + + /* Sign extend based on neff. */ +#if (NEFF == 32) + /* Faster sign extension */ + pteh = (unsigned long long)(signed long long)(signed long)pteh; +#else + /* General case */ + pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh; +#endif + + /* Set the ASID. */ + pteh |= get_asid() << PTEH_ASID_SHIFT; + pteh |= PTEH_VALID; + + /* Set PTEL register, set_pte has performed the sign extension */ + ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ + + tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb); + next = tlbp->next; + __flush_tlb_slot(next); + asm volatile ("putcfg %0,1,%2\n\n\t" + "putcfg %0,0,%1\n" + : : "r" (next), "r" (pteh), "r" (ptel) ); + + next += TLB_STEP; + if (next > tlbp->last) next = tlbp->first; + tlbp->next = next; + +} + +static int handle_vmalloc_fault(struct mm_struct *mm, + unsigned long protection_flags, + unsigned long long textaccess, + unsigned long address) +{ + pgd_t *dir; + pud_t *pud; + pmd_t *pmd; + static pte_t *pte; + pte_t entry; + + dir = pgd_offset_k(address); + + pud = pud_offset(dir, address); + if (pud_none_or_clear_bad(pud)) + return 0; + + pmd = pmd_offset(pud, address); + if (pmd_none_or_clear_bad(pmd)) + return 0; + + pte = pte_offset_kernel(pmd, address); + entry = *pte; + + if (pte_none(entry) || !pte_present(entry)) + return 0; + if ((pte_val(entry) & protection_flags) != protection_flags) + return 0; + + __do_tlb_refill(address, textaccess, pte); + + return 1; +} + +static int handle_tlbmiss(struct mm_struct *mm, + unsigned long long protection_flags, + unsigned long long textaccess, + unsigned long address) +{ + pgd_t *dir; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + + /* NB. The PGD currently only contains a single entry - there is no + page table tree stored for the top half of the address space since + virtual pages in that region should never be mapped in user mode. + (In kernel mode, the only things in that region are the 512Mb super + page (locked in), and vmalloc (modules) + I/O device pages (handled + by handle_vmalloc_fault), so no PGD for the upper half is required + by kernel mode either). + + See how mm->pgd is allocated and initialised in pgd_alloc to see why + the next test is necessary. - RPC */ + if (address >= (unsigned long) TASK_SIZE) + /* upper half - never has page table entries. */ + return 0; + + dir = pgd_offset(mm, address); + if (pgd_none(*dir) || !pgd_present(*dir)) + return 0; + if (!pgd_present(*dir)) + return 0; + + pud = pud_offset(dir, address); + if (pud_none(*pud) || !pud_present(*pud)) + return 0; + + pmd = pmd_offset(pud, address); + if (pmd_none(*pmd) || !pmd_present(*pmd)) + return 0; + + pte = pte_offset_kernel(pmd, address); + entry = *pte; + + if (pte_none(entry) || !pte_present(entry)) + return 0; + + /* + * If the page doesn't have sufficient protection bits set to + * service the kind of fault being handled, there's not much + * point doing the TLB refill. Punt the fault to the general + * handler. + */ + if ((pte_val(entry) & protection_flags) != protection_flags) + return 0; + + __do_tlb_refill(address, textaccess, pte); + + return 1; +} + +/* + * Put all this information into one structure so that everything is just + * arithmetic relative to a single base address. This reduces the number + * of movi/shori pairs needed just to load addresses of static data. + */ +struct expevt_lookup { + unsigned short protection_flags[8]; + unsigned char is_text_access[8]; + unsigned char is_write_access[8]; +}; + +#define PRU (1<<9) +#define PRW (1<<8) +#define PRX (1<<7) +#define PRR (1<<6) + +#define DIRTY (_PAGE_DIRTY | _PAGE_ACCESSED) +#define YOUNG (_PAGE_ACCESSED) + +/* Sized as 8 rather than 4 to allow checking the PTE's PRU bit against whether + the fault happened in user mode or privileged mode. */ +static struct expevt_lookup expevt_lookup_table = { + .protection_flags = {PRX, PRX, 0, 0, PRR, PRR, PRW, PRW}, + .is_text_access = {1, 1, 0, 0, 0, 0, 0, 0} +}; + +/* + This routine handles page faults that can be serviced just by refilling a + TLB entry from an existing page table entry. (This case represents a very + large majority of page faults.) Return 1 if the fault was successfully + handled. Return 0 if the fault could not be handled. (This leads into the + general fault handling in fault.c which deals with mapping file-backed + pages, stack growth, segmentation faults, swapping etc etc) + */ +asmlinkage int do_fast_page_fault(unsigned long long ssr_md, + unsigned long long expevt, + unsigned long address) +{ + struct task_struct *tsk; + struct mm_struct *mm; + unsigned long long textaccess; + unsigned long long protection_flags; + unsigned long long index; + unsigned long long expevt4; + + /* The next few lines implement a way of hashing EXPEVT into a + * small array index which can be used to lookup parameters + * specific to the type of TLBMISS being handled. + * + * Note: + * ITLBMISS has EXPEVT==0xa40 + * RTLBMISS has EXPEVT==0x040 + * WTLBMISS has EXPEVT==0x060 + */ + expevt4 = (expevt >> 4); + /* TODO : xor ssr_md into this expression too. Then we can check + * that PRU is set when it needs to be. */ + index = expevt4 ^ (expevt4 >> 5); + index &= 7; + protection_flags = expevt_lookup_table.protection_flags[index]; + textaccess = expevt_lookup_table.is_text_access[index]; + + /* SIM + * Note this is now called with interrupts still disabled + * This is to cope with being called for a missing IO port + * address with interrupts disabled. This should be fixed as + * soon as we have a better 'fast path' miss handler. + * + * Plus take care how you try and debug this stuff. + * For example, writing debug data to a port which you + * have just faulted on is not going to work. + */ + + tsk = current; + mm = tsk->mm; + + if ((address >= VMALLOC_START && address < VMALLOC_END) || + (address >= IOBASE_VADDR && address < IOBASE_END)) { + if (ssr_md) + /* + * Process-contexts can never have this address + * range mapped + */ + if (handle_vmalloc_fault(mm, protection_flags, + textaccess, address)) + return 1; + } else if (!in_interrupt() && mm) { + if (handle_tlbmiss(mm, protection_flags, textaccess, address)) + return 1; + } + + return 0; +} diff -puN arch/sh/mm/init.c~git-sh arch/sh/mm/init.c --- a/arch/sh/mm/init.c~git-sh +++ a/arch/sh/mm/init.c @@ -23,9 +23,7 @@ DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); pgd_t swapper_pg_dir[PTRS_PER_PGD]; - -void (*copy_page)(void *from, void *to); -void (*clear_page)(void *to); +unsigned long cached_to_uncached = 0; void show_mem(void) { @@ -102,7 +100,8 @@ static void set_pte_phys(unsigned long a set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot)); - flush_tlb_one(get_asid(), addr); + if (cached_to_uncached) + flush_tlb_one(get_asid(), addr); } /* @@ -131,6 +130,37 @@ void __set_fixmap(enum fixed_addresses i set_pte_phys(address, phys, prot); } + +void __init page_table_range_init(unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + int pgd_idx; + unsigned long vaddr; + + vaddr = start & PMD_MASK; + end = (end + PMD_SIZE - 1) & PMD_MASK; + pgd_idx = pgd_index(vaddr); + pgd = pgd_base + pgd_idx; + + for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { + BUG_ON(pgd_none(*pgd)); + pud = pud_offset(pgd, 0); + BUG_ON(pud_none(*pud)); + pmd = pmd_offset(pud, 0); + + if (!pmd_present(*pmd)) { + pte_t *pte_table; + pte_table = (pte_t *)alloc_bootmem_low_pages(PAGE_SIZE); + memset(pte_table, 0, PAGE_SIZE); + pmd_populate_kernel(&init_mm, pmd, pte_table); + } + + vaddr += PMD_SIZE; + } +} #endif /* CONFIG_MMU */ /* @@ -150,6 +180,11 @@ void __init paging_init(void) * check for a null value. */ set_TTB(swapper_pg_dir); + /* Populate the relevant portions of swapper_pg_dir so that + * we can use the fixmap entries without calling kmalloc. + * pte's will be filled in by __set_fixmap(). */ + page_table_range_init(FIXADDR_START, FIXADDR_TOP, swapper_pg_dir); + memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); for_each_online_node(nid) { @@ -167,9 +202,22 @@ void __init paging_init(void) } free_area_init_nodes(max_zone_pfns); + + /* Set up the uncached fixmap */ + set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start)); + +#ifdef CONFIG_29BIT + /* + * Handle trivial transitions between cached and uncached + * segments, making use of the 1:1 mapping relationship in + * 512MB lowmem. + */ + cached_to_uncached = P2SEG - P1SEG; +#endif } static struct kcore_list kcore_mem, kcore_vmalloc; +int after_bootmem = 0; void __init mem_init(void) { @@ -202,17 +250,7 @@ void __init mem_init(void) memset(empty_zero_page, 0, PAGE_SIZE); __flush_wback_region(empty_zero_page, PAGE_SIZE); - /* - * Setup wrappers for copy/clear_page(), these will get overridden - * later in the boot process if a better method is available. - */ -#ifdef CONFIG_MMU - copy_page = copy_page_slow; - clear_page = clear_page_slow; -#else - copy_page = copy_page_nommu; - clear_page = clear_page_nommu; -#endif + after_bootmem = 1; codesize = (unsigned long) &_etext - (unsigned long) &_text; datasize = (unsigned long) &_edata - (unsigned long) &_etext; diff -puN arch/sh/mm/ioremap.c~git-sh /dev/null --- a/arch/sh/mm/ioremap.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * arch/sh/mm/ioremap.c - * - * Re-map IO memory to kernel address space so that we can access it. - * This is needed for high PCI addresses that aren't mapped in the - * 640k-1MB IO memory area on PC's - * - * (C) Copyright 1995 1996 Linus Torvalds - * (C) Copyright 2005, 2006 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file "COPYING" in the main directory of this - * archive for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Remap an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access high addresses - * directly. - * - * NOTE! We need to allow non-page-aligned mappings too: we will obviously - * have to convert them into an offset in a page-aligned mapping, but the - * caller shouldn't need to know that small detail. - */ -void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, - unsigned long flags) -{ - struct vm_struct * area; - unsigned long offset, last_addr, addr, orig_addr; - pgprot_t pgprot; - - /* Don't allow wraparound or zero size */ - last_addr = phys_addr + size - 1; - if (!size || last_addr < phys_addr) - return NULL; - - /* - * If we're on an SH7751 or SH7780 PCI controller, PCI memory is - * mapped at the end of the address space (typically 0xfd000000) - * in a non-translatable area, so mapping through page tables for - * this area is not only pointless, but also fundamentally - * broken. Just return the physical address instead. - * - * For boards that map a small PCI memory aperture somewhere in - * P1/P2 space, ioremap() will already do the right thing, - * and we'll never get this far. - */ - if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr)) - return (void __iomem *)phys_addr; - - /* - * Don't allow anybody to remap normal RAM that we're using.. - */ - if (phys_addr < virt_to_phys(high_memory)) - return NULL; - - /* - * Mappings have to be page-aligned - */ - offset = phys_addr & ~PAGE_MASK; - phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr+1) - phys_addr; - - /* - * Ok, go for it.. - */ - area = get_vm_area(size, VM_IOREMAP); - if (!area) - return NULL; - area->phys_addr = phys_addr; - orig_addr = addr = (unsigned long)area->addr; - -#ifdef CONFIG_32BIT - /* - * First try to remap through the PMB once a valid VMA has been - * established. Smaller allocations (or the rest of the size - * remaining after a PMB mapping due to the size not being - * perfectly aligned on a PMB size boundary) are then mapped - * through the UTLB using conventional page tables. - * - * PMB entries are all pre-faulted. - */ - if (unlikely(size >= 0x1000000)) { - unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); - - if (likely(mapped)) { - addr += mapped; - phys_addr += mapped; - size -= mapped; - } - } -#endif - - pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); - if (likely(size)) - if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { - vunmap((void *)orig_addr); - return NULL; - } - - return (void __iomem *)(offset + (char *)orig_addr); -} -EXPORT_SYMBOL(__ioremap); - -void __iounmap(void __iomem *addr) -{ - unsigned long vaddr = (unsigned long __force)addr; - struct vm_struct *p; - - if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr)) - return; - -#ifdef CONFIG_32BIT - /* - * Purge any PMB entries that may have been established for this - * mapping, then proceed with conventional VMA teardown. - * - * XXX: Note that due to the way that remove_vm_area() does - * matching of the resultant VMA, we aren't able to fast-forward - * the address past the PMB space until the end of the VMA where - * the page tables reside. As such, unmap_vm_area() will be - * forced to linearly scan over the area until it finds the page - * tables where PTEs that need to be unmapped actually reside, - * which is far from optimal. Perhaps we need to use a separate - * VMA for the PMB mappings? - * -- PFM. - */ - pmb_unmap(vaddr); -#endif - - p = remove_vm_area((void *)(vaddr & PAGE_MASK)); - if (!p) { - printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); - return; - } - - kfree(p); -} -EXPORT_SYMBOL(__iounmap); diff -puN /dev/null arch/sh/mm/ioremap_32.c --- /dev/null +++ a/arch/sh/mm/ioremap_32.c @@ -0,0 +1,150 @@ +/* + * arch/sh/mm/ioremap.c + * + * Re-map IO memory to kernel address space so that we can access it. + * This is needed for high PCI addresses that aren't mapped in the + * 640k-1MB IO memory area on PC's + * + * (C) Copyright 1995 1996 Linus Torvalds + * (C) Copyright 2005, 2006 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of this + * archive for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. + */ +void __iomem *__ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) +{ + struct vm_struct * area; + unsigned long offset, last_addr, addr, orig_addr; + pgprot_t pgprot; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + /* + * If we're on an SH7751 or SH7780 PCI controller, PCI memory is + * mapped at the end of the address space (typically 0xfd000000) + * in a non-translatable area, so mapping through page tables for + * this area is not only pointless, but also fundamentally + * broken. Just return the physical address instead. + * + * For boards that map a small PCI memory aperture somewhere in + * P1/P2 space, ioremap() will already do the right thing, + * and we'll never get this far. + */ + if (is_pci_memaddr(phys_addr) && is_pci_memaddr(last_addr)) + return (void __iomem *)phys_addr; + + /* + * Don't allow anybody to remap normal RAM that we're using.. + */ + if (phys_addr < virt_to_phys(high_memory)) + return NULL; + + /* + * Mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr+1) - phys_addr; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size, VM_IOREMAP); + if (!area) + return NULL; + area->phys_addr = phys_addr; + orig_addr = addr = (unsigned long)area->addr; + +#ifdef CONFIG_32BIT + /* + * First try to remap through the PMB once a valid VMA has been + * established. Smaller allocations (or the rest of the size + * remaining after a PMB mapping due to the size not being + * perfectly aligned on a PMB size boundary) are then mapped + * through the UTLB using conventional page tables. + * + * PMB entries are all pre-faulted. + */ + if (unlikely(size >= 0x1000000)) { + unsigned long mapped = pmb_remap(addr, phys_addr, size, flags); + + if (likely(mapped)) { + addr += mapped; + phys_addr += mapped; + size -= mapped; + } + } +#endif + + pgprot = __pgprot(pgprot_val(PAGE_KERNEL_NOCACHE) | flags); + if (likely(size)) + if (ioremap_page_range(addr, addr + size, phys_addr, pgprot)) { + vunmap((void *)orig_addr); + return NULL; + } + + return (void __iomem *)(offset + (char *)orig_addr); +} +EXPORT_SYMBOL(__ioremap); + +void __iounmap(void __iomem *addr) +{ + unsigned long vaddr = (unsigned long __force)addr; + struct vm_struct *p; + + if (PXSEG(vaddr) < P3SEG || is_pci_memaddr(vaddr)) + return; + +#ifdef CONFIG_32BIT + /* + * Purge any PMB entries that may have been established for this + * mapping, then proceed with conventional VMA teardown. + * + * XXX: Note that due to the way that remove_vm_area() does + * matching of the resultant VMA, we aren't able to fast-forward + * the address past the PMB space until the end of the VMA where + * the page tables reside. As such, unmap_vm_area() will be + * forced to linearly scan over the area until it finds the page + * tables where PTEs that need to be unmapped actually reside, + * which is far from optimal. Perhaps we need to use a separate + * VMA for the PMB mappings? + * -- PFM. + */ + pmb_unmap(vaddr); +#endif + + p = remove_vm_area((void *)(vaddr & PAGE_MASK)); + if (!p) { + printk(KERN_ERR "%s: bad address %p\n", __FUNCTION__, addr); + return; + } + + kfree(p); +} +EXPORT_SYMBOL(__iounmap); diff -puN /dev/null arch/sh/mm/ioremap_64.c --- /dev/null +++ a/arch/sh/mm/ioremap_64.c @@ -0,0 +1,404 @@ +/* + * arch/sh/mm/ioremap_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * + * Mostly derived from arch/sh/mm/ioremap.c which, in turn is mostly + * derived from arch/i386/mm/ioremap.c . + * + * (C) Copyright 1995 1996 Linus Torvalds + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void shmedia_mapioaddr(unsigned long, unsigned long); +static unsigned long shmedia_ioremap(struct resource *, u32, int); + +/* + * Generic mapping function (not visible outside): + */ + +/* + * Remap an arbitrary physical address space into the kernel virtual + * address space. Needed when the kernel wants to access high addresses + * directly. + * + * NOTE! We need to allow non-page-aligned mappings too: we will obviously + * have to convert them into an offset in a page-aligned mapping, but the + * caller shouldn't need to know that small detail. + */ +void *__ioremap(unsigned long phys_addr, unsigned long size, + unsigned long flags) +{ + void * addr; + struct vm_struct * area; + unsigned long offset, last_addr; + pgprot_t pgprot; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; + + pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | + _PAGE_WRITE | _PAGE_DIRTY | + _PAGE_ACCESSED | _PAGE_SHARED | flags); + + /* + * Mappings have to be page-aligned + */ + offset = phys_addr & ~PAGE_MASK; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr + 1) - phys_addr; + + /* + * Ok, go for it.. + */ + area = get_vm_area(size, VM_IOREMAP); + pr_debug("Get vm_area returns %p addr %p\n",area,area->addr); + if (!area) + return NULL; + area->phys_addr = phys_addr; + addr = area->addr; + if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, + phys_addr, pgprot)) { + vunmap(addr); + return NULL; + } + return (void *) (offset + (char *)addr); +} +EXPORT_SYMBOL(__ioremap); + +void __iounmap(void *addr) +{ + struct vm_struct *area; + + vfree((void *) (PAGE_MASK & (unsigned long) addr)); + area = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr)); + if (!area) { + printk(KERN_ERR "iounmap: bad address %p\n", addr); + return; + } + + kfree(area); +} +EXPORT_SYMBOL(__iounmap); + +static struct resource shmedia_iomap = { + .name = "shmedia_iomap", + .start = IOBASE_VADDR + PAGE_SIZE, + .end = IOBASE_END - 1, +}; + +static void shmedia_mapioaddr(unsigned long pa, unsigned long va); +static void shmedia_unmapioaddr(unsigned long vaddr); +static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz); + +/* + * We have the same problem as the SPARC, so lets have the same comment: + * Our mini-allocator... + * Boy this is gross! We need it because we must map I/O for + * timers and interrupt controller before the kmalloc is available. + */ + +#define XNMLN 15 +#define XNRES 10 + +struct xresource { + struct resource xres; /* Must be first */ + int xflag; /* 1 == used */ + char xname[XNMLN+1]; +}; + +static struct xresource xresv[XNRES]; + +static struct xresource *xres_alloc(void) +{ + struct xresource *xrp; + int n; + + xrp = xresv; + for (n = 0; n < XNRES; n++) { + if (xrp->xflag == 0) { + xrp->xflag = 1; + return xrp; + } + xrp++; + } + return NULL; +} + +static void xres_free(struct xresource *xrp) +{ + xrp->xflag = 0; +} + +static struct resource *shmedia_find_resource(struct resource *root, + unsigned long vaddr) +{ + struct resource *res; + + for (res = root->child; res; res = res->sibling) + if (res->start <= vaddr && res->end >= vaddr) + return res; + + return NULL; +} + +static unsigned long shmedia_alloc_io(unsigned long phys, unsigned long size, + const char *name) +{ + static int printed_full = 0; + struct xresource *xres; + struct resource *res; + char *tack; + int tlen; + + if (name == NULL) name = "???"; + + if ((xres = xres_alloc()) != 0) { + tack = xres->xname; + res = &xres->xres; + } else { + if (!printed_full) { + printk("%s: done with statics, switching to kmalloc\n", + __FUNCTION__); + printed_full = 1; + } + tlen = strlen(name); + tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL); + if (!tack) + return -ENOMEM; + memset(tack, 0, sizeof(struct resource)); + res = (struct resource *) tack; + tack += sizeof (struct resource); + } + + strncpy(tack, name, XNMLN); + tack[XNMLN] = 0; + res->name = tack; + + return shmedia_ioremap(res, phys, size); +} + +static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz) +{ + unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK); + unsigned long round_sz = (offset + sz + PAGE_SIZE-1) & PAGE_MASK; + unsigned long va; + unsigned int psz; + + if (allocate_resource(&shmedia_iomap, res, round_sz, + shmedia_iomap.start, shmedia_iomap.end, + PAGE_SIZE, NULL, NULL) != 0) { + panic("alloc_io_res(%s): cannot occupy\n", + (res->name != NULL)? res->name: "???"); + } + + va = res->start; + pa &= PAGE_MASK; + + psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE; + + /* log at boot time ... */ + printk("mapioaddr: %6s [%2d page%s] va 0x%08lx pa 0x%08x\n", + ((res->name != NULL) ? res->name : "???"), + psz, psz == 1 ? " " : "s", va, pa); + + for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) { + shmedia_mapioaddr(pa, va); + va += PAGE_SIZE; + pa += PAGE_SIZE; + } + + res->start += offset; + res->end = res->start + sz - 1; /* not strictly necessary.. */ + + return res->start; +} + +static void shmedia_free_io(struct resource *res) +{ + unsigned long len = res->end - res->start + 1; + + BUG_ON((len & (PAGE_SIZE - 1)) != 0); + + while (len) { + len -= PAGE_SIZE; + shmedia_unmapioaddr(res->start + len); + } + + release_resource(res); +} + +static __init_refok void *sh64_get_page(void) +{ + extern int after_bootmem; + void *page; + + if (after_bootmem) { + page = (void *)get_zeroed_page(GFP_ATOMIC); + } else { + page = alloc_bootmem_pages(PAGE_SIZE); + } + + if (!page || ((unsigned long)page & ~PAGE_MASK)) + panic("sh64_get_page: Out of memory already?\n"); + + return page; +} + +static void shmedia_mapioaddr(unsigned long pa, unsigned long va) +{ + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep, pte; + pgprot_t prot; + unsigned long flags = 1; /* 1 = CB0-1 device */ + + pr_debug("shmedia_mapiopage pa %08lx va %08lx\n", pa, va); + + pgdp = pgd_offset_k(va); + if (pgd_none(*pgdp) || !pgd_present(*pgdp)) { + pudp = (pud_t *)sh64_get_page(); + set_pgd(pgdp, __pgd((unsigned long)pudp | _KERNPG_TABLE)); + } + + pudp = pud_offset(pgdp, va); + if (pud_none(*pudp) || !pud_present(*pudp)) { + pmdp = (pmd_t *)sh64_get_page(); + set_pud(pudp, __pud((unsigned long)pmdp | _KERNPG_TABLE)); + } + + pmdp = pmd_offset(pudp, va); + if (pmd_none(*pmdp) || !pmd_present(*pmdp) ) { + ptep = (pte_t *)sh64_get_page(); + set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE)); + } + + prot = __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | + _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SHARED | flags); + + pte = pfn_pte(pa >> PAGE_SHIFT, prot); + ptep = pte_offset_kernel(pmdp, va); + + if (!pte_none(*ptep) && + pte_val(*ptep) != pte_val(pte)) + pte_ERROR(*ptep); + + set_pte(ptep, pte); + + flush_tlb_kernel_range(va, PAGE_SIZE); +} + +static void shmedia_unmapioaddr(unsigned long vaddr) +{ + pgd_t *pgdp; + pud_t *pudp; + pmd_t *pmdp; + pte_t *ptep; + + pgdp = pgd_offset_k(vaddr); + if (pgd_none(*pgdp) || pgd_bad(*pgdp)) + return; + + pudp = pud_offset(pgdp, vaddr); + if (pud_none(*pudp) || pud_bad(*pudp)) + return; + + pmdp = pmd_offset(pudp, vaddr); + if (pmd_none(*pmdp) || pmd_bad(*pmdp)) + return; + + ptep = pte_offset_kernel(pmdp, vaddr); + + if (pte_none(*ptep) || !pte_present(*ptep)) + return; + + clear_page((void *)ptep); + pte_clear(&init_mm, vaddr, ptep); +} + +unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name) +{ + if (size < PAGE_SIZE) + size = PAGE_SIZE; + + return shmedia_alloc_io(phys, size, name); +} + +void onchip_unmap(unsigned long vaddr) +{ + struct resource *res; + unsigned int psz; + + res = shmedia_find_resource(&shmedia_iomap, vaddr); + if (!res) { + printk(KERN_ERR "%s: Failed to free 0x%08lx\n", + __FUNCTION__, vaddr); + return; + } + + psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE; + + printk(KERN_DEBUG "unmapioaddr: %6s [%2d page%s] freed\n", + res->name, psz, psz == 1 ? " " : "s"); + + shmedia_free_io(res); + + if ((char *)res >= (char *)xresv && + (char *)res < (char *)&xresv[XNRES]) { + xres_free((struct xresource *)res); + } else { + kfree(res); + } +} + +#ifdef CONFIG_PROC_FS +static int +ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, + void *data) +{ + char *p = buf, *e = buf + length; + struct resource *r; + const char *nm; + + for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) { + if (p + 32 >= e) /* Better than nothing */ + break; + if ((nm = r->name) == 0) nm = "???"; + p += sprintf(p, "%08lx-%08lx: %s\n", + (unsigned long)r->start, + (unsigned long)r->end, nm); + } + + return p-buf; +} +#endif /* CONFIG_PROC_FS */ + +static int __init register_proc_onchip(void) +{ +#ifdef CONFIG_PROC_FS + create_proc_read_entry("io_map",0,0, ioremap_proc_info, &shmedia_iomap); +#endif + return 0; +} + +__initcall(register_proc_onchip); diff -puN arch/sh/mm/pg-nommu.c~git-sh arch/sh/mm/pg-nommu.c --- a/arch/sh/mm/pg-nommu.c~git-sh +++ a/arch/sh/mm/pg-nommu.c @@ -14,12 +14,12 @@ #include #include -void copy_page_nommu(void *to, void *from) +void copy_page(void *to, void *from) { memcpy(to, from, PAGE_SIZE); } -void clear_page_nommu(void *to) +void clear_page(void *to) { memset(to, 0, PAGE_SIZE); } diff -puN arch/sh/mm/pmb.c~git-sh arch/sh/mm/pmb.c --- a/arch/sh/mm/pmb.c~git-sh +++ a/arch/sh/mm/pmb.c @@ -27,6 +27,7 @@ #include #include #include +#include #define NR_PMB_ENTRIES 16 @@ -162,18 +163,18 @@ repeat: return 0; } -int set_pmb_entry(struct pmb_entry *pmbe) +int __uses_jump_to_uncached set_pmb_entry(struct pmb_entry *pmbe) { int ret; - jump_to_P2(); + jump_to_uncached(); ret = __set_pmb_entry(pmbe->vpn, pmbe->ppn, pmbe->flags, &pmbe->entry); - back_to_P1(); + back_to_cached(); return ret; } -void clear_pmb_entry(struct pmb_entry *pmbe) +void __uses_jump_to_uncached clear_pmb_entry(struct pmb_entry *pmbe) { unsigned int entry = pmbe->entry; unsigned long addr; @@ -187,7 +188,7 @@ void clear_pmb_entry(struct pmb_entry *p entry >= NR_PMB_ENTRIES)) return; - jump_to_P2(); + jump_to_uncached(); /* Clear V-bit */ addr = mk_pmb_addr(entry); @@ -196,7 +197,7 @@ void clear_pmb_entry(struct pmb_entry *p addr = mk_pmb_data(entry); ctrl_outl(ctrl_inl(addr) & ~PMB_V, addr); - back_to_P1(); + back_to_cached(); clear_bit(entry, &pmb_map); } @@ -301,17 +302,17 @@ static void pmb_cache_ctor(struct kmem_c pmbe->entry = PMB_NO_ENTRY; } -static int __init pmb_init(void) +static int __uses_jump_to_uncached pmb_init(void) { unsigned int nr_entries = ARRAY_SIZE(pmb_init_map); - unsigned int entry; + unsigned int entry, i; BUG_ON(unlikely(nr_entries >= NR_PMB_ENTRIES)); pmb_cache = kmem_cache_create("pmb", sizeof(struct pmb_entry), 0, SLAB_PANIC, pmb_cache_ctor); - jump_to_P2(); + jump_to_uncached(); /* * Ordering is important, P2 must be mapped in the PMB before we @@ -329,7 +330,12 @@ static int __init pmb_init(void) /* PMB.SE and UB[7] */ ctrl_outl((1 << 31) | (1 << 7), PMB_PASCR); - back_to_P1(); + /* Flush out the TLB */ + i = ctrl_inl(MMUCR); + i |= MMUCR_TI; + ctrl_outl(i, MMUCR); + + back_to_cached(); return 0; } diff -puN arch/sh/mm/tlb-flush.c~git-sh /dev/null --- a/arch/sh/mm/tlb-flush.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * TLB flushing operations for SH with an MMU. - * - * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include - -void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - unsigned int cpu = smp_processor_id(); - - if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) { - unsigned long flags; - unsigned long asid; - unsigned long saved_asid = MMU_NO_ASID; - - asid = cpu_asid(cpu, vma->vm_mm); - page &= PAGE_MASK; - - local_irq_save(flags); - if (vma->vm_mm != current->mm) { - saved_asid = get_asid(); - set_asid(asid); - } - local_flush_tlb_one(asid, page); - if (saved_asid != MMU_NO_ASID) - set_asid(saved_asid); - local_irq_restore(flags); - } -} - -void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - unsigned int cpu = smp_processor_id(); - - if (cpu_context(cpu, mm) != NO_CONTEXT) { - unsigned long flags; - int size; - - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */ - cpu_context(cpu, mm) = NO_CONTEXT; - if (mm == current->mm) - activate_context(mm, cpu); - } else { - unsigned long asid; - unsigned long saved_asid = MMU_NO_ASID; - - asid = cpu_asid(cpu, mm); - start &= PAGE_MASK; - end += (PAGE_SIZE - 1); - end &= PAGE_MASK; - if (mm != current->mm) { - saved_asid = get_asid(); - set_asid(asid); - } - while (start < end) { - local_flush_tlb_one(asid, start); - start += PAGE_SIZE; - } - if (saved_asid != MMU_NO_ASID) - set_asid(saved_asid); - } - local_irq_restore(flags); - } -} - -void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - unsigned int cpu = smp_processor_id(); - unsigned long flags; - int size; - - local_irq_save(flags); - size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; - if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */ - local_flush_tlb_all(); - } else { - unsigned long asid; - unsigned long saved_asid = get_asid(); - - asid = cpu_asid(cpu, &init_mm); - start &= PAGE_MASK; - end += (PAGE_SIZE - 1); - end &= PAGE_MASK; - set_asid(asid); - while (start < end) { - local_flush_tlb_one(asid, start); - start += PAGE_SIZE; - } - set_asid(saved_asid); - } - local_irq_restore(flags); -} - -void local_flush_tlb_mm(struct mm_struct *mm) -{ - unsigned int cpu = smp_processor_id(); - - /* Invalidate all TLB of this process. */ - /* Instead of invalidating each TLB, we get new MMU context. */ - if (cpu_context(cpu, mm) != NO_CONTEXT) { - unsigned long flags; - - local_irq_save(flags); - cpu_context(cpu, mm) = NO_CONTEXT; - if (mm == current->mm) - activate_context(mm, cpu); - local_irq_restore(flags); - } -} - -void local_flush_tlb_all(void) -{ - unsigned long flags, status; - - /* - * Flush all the TLB. - * - * Write to the MMU control register's bit: - * TF-bit for SH-3, TI-bit for SH-4. - * It's same position, bit #2. - */ - local_irq_save(flags); - status = ctrl_inl(MMUCR); - status |= 0x04; - ctrl_outl(status, MMUCR); - ctrl_barrier(); - local_irq_restore(flags); -} diff -puN arch/sh/mm/tlb-nommu.c~git-sh arch/sh/mm/tlb-nommu.c --- a/arch/sh/mm/tlb-nommu.c~git-sh +++ a/arch/sh/mm/tlb-nommu.c @@ -9,6 +9,7 @@ */ #include #include +#include /* * Nothing too terribly exciting here .. @@ -49,3 +50,12 @@ void update_mmu_cache(struct vm_area_str { BUG(); } + +void __init page_table_range_init(unsigned long start, unsigned long end, + pgd_t *pgd_base) +{ +} + +void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) +{ +} diff -puN arch/sh/mm/tlb-sh4.c~git-sh arch/sh/mm/tlb-sh4.c --- a/arch/sh/mm/tlb-sh4.c~git-sh +++ a/arch/sh/mm/tlb-sh4.c @@ -79,7 +79,8 @@ void update_mmu_cache(struct vm_area_str local_irq_restore(flags); } -void local_flush_tlb_one(unsigned long asid, unsigned long page) +void __uses_jump_to_uncached local_flush_tlb_one(unsigned long asid, + unsigned long page) { unsigned long addr, data; @@ -91,7 +92,7 @@ void local_flush_tlb_one(unsigned long a */ addr = MMU_UTLB_ADDRESS_ARRAY | MMU_PAGE_ASSOC_BIT; data = page | asid; /* VALID bit is off */ - jump_to_P2(); + jump_to_uncached(); ctrl_outl(data, addr); - back_to_P1(); + back_to_cached(); } diff -puN /dev/null arch/sh/mm/tlb-sh5.c --- /dev/null +++ a/arch/sh/mm/tlb-sh5.c @@ -0,0 +1,164 @@ +/* + * arch/sh/mm/tlb-sh5.c + * + * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2003 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include + +/** + * sh64_tlb_init + * + * Perform initial setup for the DTLB and ITLB. + */ +int __init sh64_tlb_init(void) +{ + /* Assign some sane DTLB defaults */ + cpu_data->dtlb.entries = 64; + cpu_data->dtlb.step = 0x10; + + cpu_data->dtlb.first = DTLB_FIXED | cpu_data->dtlb.step; + cpu_data->dtlb.next = cpu_data->dtlb.first; + + cpu_data->dtlb.last = DTLB_FIXED | + ((cpu_data->dtlb.entries - 1) * + cpu_data->dtlb.step); + + /* And again for the ITLB */ + cpu_data->itlb.entries = 64; + cpu_data->itlb.step = 0x10; + + cpu_data->itlb.first = ITLB_FIXED | cpu_data->itlb.step; + cpu_data->itlb.next = cpu_data->itlb.first; + cpu_data->itlb.last = ITLB_FIXED | + ((cpu_data->itlb.entries - 1) * + cpu_data->itlb.step); + + return 0; +} + +/** + * sh64_next_free_dtlb_entry + * + * Find the next available DTLB entry + */ +unsigned long long sh64_next_free_dtlb_entry(void) +{ + return cpu_data->dtlb.next; +} + +/** + * sh64_get_wired_dtlb_entry + * + * Allocate a wired (locked-in) entry in the DTLB + */ +unsigned long long sh64_get_wired_dtlb_entry(void) +{ + unsigned long long entry = sh64_next_free_dtlb_entry(); + + cpu_data->dtlb.first += cpu_data->dtlb.step; + cpu_data->dtlb.next += cpu_data->dtlb.step; + + return entry; +} + +/** + * sh64_put_wired_dtlb_entry + * + * @entry: Address of TLB slot. + * + * Free a wired (locked-in) entry in the DTLB. + * + * Works like a stack, last one to allocate must be first one to free. + */ +int sh64_put_wired_dtlb_entry(unsigned long long entry) +{ + __flush_tlb_slot(entry); + + /* + * We don't do any particularly useful tracking of wired entries, + * so this approach works like a stack .. last one to be allocated + * has to be the first one to be freed. + * + * We could potentially load wired entries into a list and work on + * rebalancing the list periodically (which also entails moving the + * contents of a TLB entry) .. though I have a feeling that this is + * more trouble than it's worth. + */ + + /* + * Entry must be valid .. we don't want any ITLB addresses! + */ + if (entry <= DTLB_FIXED) + return -EINVAL; + + /* + * Next, check if we're within range to be freed. (ie, must be the + * entry beneath the first 'free' entry! + */ + if (entry < (cpu_data->dtlb.first - cpu_data->dtlb.step)) + return -EINVAL; + + /* If we are, then bring this entry back into the list */ + cpu_data->dtlb.first -= cpu_data->dtlb.step; + cpu_data->dtlb.next = entry; + + return 0; +} + +/** + * sh64_setup_tlb_slot + * + * @config_addr: Address of TLB slot. + * @eaddr: Virtual address. + * @asid: Address Space Identifier. + * @paddr: Physical address. + * + * Load up a virtual<->physical translation for @eaddr<->@paddr in the + * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry). + */ +inline void sh64_setup_tlb_slot(unsigned long long config_addr, + unsigned long eaddr, + unsigned long asid, + unsigned long paddr) +{ + unsigned long long pteh, ptel; + + /* Sign extension */ +#if (NEFF == 32) + pteh = (unsigned long long)(signed long long)(signed long) eaddr; +#else +#error "Can't sign extend more than 32 bits yet" +#endif + pteh &= PAGE_MASK; + pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID; +#if (NEFF == 32) + ptel = (unsigned long long)(signed long long)(signed long) paddr; +#else +#error "Can't sign extend more than 32 bits yet" +#endif + ptel &= PAGE_MASK; + ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE); + + asm volatile("putcfg %0, 1, %1\n\t" + "putcfg %0, 0, %2\n" + : : "r" (config_addr), "r" (ptel), "r" (pteh)); +} + +/** + * sh64_teardown_tlb_slot + * + * @config_addr: Address of TLB slot. + * + * Teardown any existing mapping in the TLB slot @config_addr. + */ +inline void sh64_teardown_tlb_slot(unsigned long long config_addr) + __attribute__ ((alias("__flush_tlb_slot"))); diff -puN /dev/null arch/sh/mm/tlbflush_32.c --- /dev/null +++ a/arch/sh/mm/tlbflush_32.c @@ -0,0 +1,140 @@ +/* + * TLB flushing operations for SH with an MMU. + * + * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + unsigned int cpu = smp_processor_id(); + + if (vma->vm_mm && cpu_context(cpu, vma->vm_mm) != NO_CONTEXT) { + unsigned long flags; + unsigned long asid; + unsigned long saved_asid = MMU_NO_ASID; + + asid = cpu_asid(cpu, vma->vm_mm); + page &= PAGE_MASK; + + local_irq_save(flags); + if (vma->vm_mm != current->mm) { + saved_asid = get_asid(); + set_asid(asid); + } + local_flush_tlb_one(asid, page); + if (saved_asid != MMU_NO_ASID) + set_asid(saved_asid); + local_irq_restore(flags); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) != NO_CONTEXT) { + unsigned long flags; + int size; + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */ + cpu_context(cpu, mm) = NO_CONTEXT; + if (mm == current->mm) + activate_context(mm, cpu); + } else { + unsigned long asid; + unsigned long saved_asid = MMU_NO_ASID; + + asid = cpu_asid(cpu, mm); + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; + if (mm != current->mm) { + saved_asid = get_asid(); + set_asid(asid); + } + while (start < end) { + local_flush_tlb_one(asid, start); + start += PAGE_SIZE; + } + if (saved_asid != MMU_NO_ASID) + set_asid(saved_asid); + } + local_irq_restore(flags); + } +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + unsigned int cpu = smp_processor_id(); + unsigned long flags; + int size; + + local_irq_save(flags); + size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT; + if (size > (MMU_NTLB_ENTRIES/4)) { /* Too many TLB to flush */ + local_flush_tlb_all(); + } else { + unsigned long asid; + unsigned long saved_asid = get_asid(); + + asid = cpu_asid(cpu, &init_mm); + start &= PAGE_MASK; + end += (PAGE_SIZE - 1); + end &= PAGE_MASK; + set_asid(asid); + while (start < end) { + local_flush_tlb_one(asid, start); + start += PAGE_SIZE; + } + set_asid(saved_asid); + } + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + unsigned int cpu = smp_processor_id(); + + /* Invalidate all TLB of this process. */ + /* Instead of invalidating each TLB, we get new MMU context. */ + if (cpu_context(cpu, mm) != NO_CONTEXT) { + unsigned long flags; + + local_irq_save(flags); + cpu_context(cpu, mm) = NO_CONTEXT; + if (mm == current->mm) + activate_context(mm, cpu); + local_irq_restore(flags); + } +} + +void local_flush_tlb_all(void) +{ + unsigned long flags, status; + + /* + * Flush all the TLB. + * + * Write to the MMU control register's bit: + * TF-bit for SH-3, TI-bit for SH-4. + * It's same position, bit #2. + */ + local_irq_save(flags); + status = ctrl_inl(MMUCR); + status |= 0x04; + ctrl_outl(status, MMUCR); + ctrl_barrier(); + local_irq_restore(flags); +} diff -puN /dev/null arch/sh/mm/tlbflush_64.c --- /dev/null +++ a/arch/sh/mm/tlbflush_64.c @@ -0,0 +1,475 @@ +/* + * arch/sh/mm/tlb-flush_64.c + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Richard Curnow (/proc/tlb, bug fixes) + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern void die(const char *,struct pt_regs *,long); + +#define PFLAG(val,flag) (( (val) & (flag) ) ? #flag : "" ) +#define PPROT(flag) PFLAG(pgprot_val(prot),flag) + +static inline void print_prots(pgprot_t prot) +{ + printk("prot is 0x%08lx\n",pgprot_val(prot)); + + printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ), + PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER)); +} + +static inline void print_vma(struct vm_area_struct *vma) +{ + printk("vma start 0x%08lx\n", vma->vm_start); + printk("vma end 0x%08lx\n", vma->vm_end); + + print_prots(vma->vm_page_prot); + printk("vm_flags 0x%08lx\n", vma->vm_flags); +} + +static inline void print_task(struct task_struct *tsk) +{ + printk("Task pid %d\n", task_pid_nr(tsk)); +} + +static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address) +{ + pgd_t *dir; + pud_t *pud; + pmd_t *pmd; + pte_t *pte; + pte_t entry; + + dir = pgd_offset(mm, address); + if (pgd_none(*dir)) + return NULL; + + pud = pud_offset(dir, address); + if (pud_none(*pud)) + return NULL; + + pmd = pmd_offset(pud, address); + if (pmd_none(*pmd)) + return NULL; + + pte = pte_offset_kernel(pmd, address); + entry = *pte; + if (pte_none(entry) || !pte_present(entry)) + return NULL; + + return pte; +} + +/* + * This routine handles page faults. It determines the address, + * and the problem, and then passes it off to one of the appropriate + * routines. + */ +asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, + unsigned long textaccess, unsigned long address) +{ + struct task_struct *tsk; + struct mm_struct *mm; + struct vm_area_struct * vma; + const struct exception_table_entry *fixup; + pte_t *pte; + int fault; + + /* SIM + * Note this is now called with interrupts still disabled + * This is to cope with being called for a missing IO port + * address with interrupts disabled. This should be fixed as + * soon as we have a better 'fast path' miss handler. + * + * Plus take care how you try and debug this stuff. + * For example, writing debug data to a port which you + * have just faulted on is not going to work. + */ + + tsk = current; + mm = tsk->mm; + + /* Not an IO address, so reenable interrupts */ + local_irq_enable(); + + /* + * If we're in an interrupt or have no user + * context, we must not take the fault.. + */ + if (in_atomic() || !mm) + goto no_context; + + /* TLB misses upon some cache flushes get done under cli() */ + down_read(&mm->mmap_sem); + + vma = find_vma(mm, address); + + if (!vma) { +#ifdef DEBUG_FAULT + print_task(tsk); + printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", + __FUNCTION__,__LINE__, + address,regs->pc,textaccess,writeaccess); + show_regs(regs); +#endif + goto bad_area; + } + if (vma->vm_start <= address) { + goto good_area; + } + + if (!(vma->vm_flags & VM_GROWSDOWN)) { +#ifdef DEBUG_FAULT + print_task(tsk); + printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", + __FUNCTION__,__LINE__, + address,regs->pc,textaccess,writeaccess); + show_regs(regs); + + print_vma(vma); +#endif + goto bad_area; + } + if (expand_stack(vma, address)) { +#ifdef DEBUG_FAULT + print_task(tsk); + printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", + __FUNCTION__,__LINE__, + address,regs->pc,textaccess,writeaccess); + show_regs(regs); +#endif + goto bad_area; + } +/* + * Ok, we have a good vm_area for this memory access, so + * we can handle it.. + */ +good_area: + if (textaccess) { + if (!(vma->vm_flags & VM_EXEC)) + goto bad_area; + } else { + if (writeaccess) { + if (!(vma->vm_flags & VM_WRITE)) + goto bad_area; + } else { + if (!(vma->vm_flags & VM_READ)) + goto bad_area; + } + } + + /* + * If for any reason at all we couldn't handle the fault, + * make sure we exit gracefully rather than endlessly redo + * the fault. + */ +survive: + fault = handle_mm_fault(mm, vma, address, writeaccess); + 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) + tsk->maj_flt++; + else + tsk->min_flt++; + + /* If we get here, the page fault has been handled. Do the TLB refill + now from the newly-setup PTE, to avoid having to fault again right + away on the same instruction. */ + pte = lookup_pte (mm, address); + if (!pte) { + /* From empirical evidence, we can get here, due to + !pte_present(pte). (e.g. if a swap-in occurs, and the page + is swapped back out again before the process that wanted it + gets rescheduled?) */ + goto no_pte; + } + + __do_tlb_refill(address, textaccess, pte); + +no_pte: + + up_read(&mm->mmap_sem); + return; + +/* + * Something tried to access memory that isn't in our memory map.. + * Fix it, but check if it's kernel or user first.. + */ +bad_area: +#ifdef DEBUG_FAULT + printk("fault:bad area\n"); +#endif + up_read(&mm->mmap_sem); + + if (user_mode(regs)) { + static int count=0; + siginfo_t info; + if (count < 4) { + /* This is really to help debug faults when starting + * usermode, so only need a few */ + count++; + printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n", + address, task_pid_nr(current), current->comm, + (unsigned long) regs->pc); +#if 0 + show_regs(regs); +#endif + } + if (is_global_init(tsk)) { + panic("INIT had user mode bad_area\n"); + } + tsk->thread.address = address; + tsk->thread.error_code = writeaccess; + info.si_signo = SIGSEGV; + info.si_errno = 0; + info.si_addr = (void *) address; + force_sig_info(SIGSEGV, &info, tsk); + return; + } + +no_context: +#ifdef DEBUG_FAULT + printk("fault:No context\n"); +#endif + /* Are we prepared to handle this kernel fault? */ + fixup = search_exception_tables(regs->pc); + if (fixup) { + regs->pc = fixup->fixup; + return; + } + +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + * + */ + if (address < PAGE_SIZE) + printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); + else + printk(KERN_ALERT "Unable to handle kernel paging request"); + printk(" at virtual address %08lx\n", address); + printk(KERN_ALERT "pc = %08Lx%08Lx\n", regs->pc >> 32, regs->pc & 0xffffffff); + die("Oops", regs, writeaccess); + do_exit(SIGKILL); + +/* + * We ran out of memory, or some other thing happened to us that made + * us unable to handle the page fault gracefully. + */ +out_of_memory: + if (is_global_init(current)) { + panic("INIT out of memory\n"); + yield(); + goto survive; + } + printk("fault:Out of memory\n"); + up_read(&mm->mmap_sem); + if (is_global_init(current)) { + yield(); + down_read(&mm->mmap_sem); + goto survive; + } + printk("VM: killing process %s\n", tsk->comm); + if (user_mode(regs)) + do_group_exit(SIGKILL); + goto no_context; + +do_sigbus: + printk("fault:Do sigbus\n"); + up_read(&mm->mmap_sem); + + /* + * Send a sigbus, regardless of whether we were in kernel + * or user mode. + */ + tsk->thread.address = address; + tsk->thread.error_code = writeaccess; + tsk->thread.trap_no = 14; + force_sig(SIGBUS, tsk); + + /* Kernel mode? Handle exceptions or die */ + if (!user_mode(regs)) + goto no_context; +} + +void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte) +{ + /* + * This appears to get called once for every pte entry that gets + * established => I don't think it's efficient to try refilling the + * TLBs with the pages - some may not get accessed even. Also, for + * executable pages, it is impossible to determine reliably here which + * TLB they should be mapped into (or both even). + * + * So, just do nothing here and handle faults on demand. In the + * TLBMISS handling case, the refill is now done anyway after the pte + * has been fixed up, so that deals with most useful cases. + */ +} + +void local_flush_tlb_one(unsigned long asid, unsigned long page) +{ + unsigned long long match, pteh=0, lpage; + unsigned long tlb; + + /* + * Sign-extend based on neff. + */ + lpage = (page & NEFF_SIGN) ? (page | NEFF_MASK) : page; + match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID; + match |= lpage; + + for_each_itlb_entry(tlb) { + asm volatile ("getcfg %1, 0, %0" + : "=r" (pteh) + : "r" (tlb) ); + + if (pteh == match) { + __flush_tlb_slot(tlb); + break; + } + } + + for_each_dtlb_entry(tlb) { + asm volatile ("getcfg %1, 0, %0" + : "=r" (pteh) + : "r" (tlb) ); + + if (pteh == match) { + __flush_tlb_slot(tlb); + break; + } + + } +} + +void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page) +{ + unsigned long flags; + + if (vma->vm_mm) { + page &= PAGE_MASK; + local_irq_save(flags); + local_flush_tlb_one(get_asid(), page); + local_irq_restore(flags); + } +} + +void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end) +{ + unsigned long flags; + unsigned long long match, pteh=0, pteh_epn, pteh_low; + unsigned long tlb; + unsigned int cpu = smp_processor_id(); + struct mm_struct *mm; + + mm = vma->vm_mm; + if (cpu_context(cpu, mm) == NO_CONTEXT) + return; + + local_irq_save(flags); + + start &= PAGE_MASK; + end &= PAGE_MASK; + + match = (cpu_asid(cpu, mm) << PTEH_ASID_SHIFT) | PTEH_VALID; + + /* Flush ITLB */ + for_each_itlb_entry(tlb) { + asm volatile ("getcfg %1, 0, %0" + : "=r" (pteh) + : "r" (tlb) ); + + pteh_epn = pteh & PAGE_MASK; + pteh_low = pteh & ~PAGE_MASK; + + if (pteh_low == match && pteh_epn >= start && pteh_epn <= end) + __flush_tlb_slot(tlb); + } + + /* Flush DTLB */ + for_each_dtlb_entry(tlb) { + asm volatile ("getcfg %1, 0, %0" + : "=r" (pteh) + : "r" (tlb) ); + + pteh_epn = pteh & PAGE_MASK; + pteh_low = pteh & ~PAGE_MASK; + + if (pteh_low == match && pteh_epn >= start && pteh_epn <= end) + __flush_tlb_slot(tlb); + } + + local_irq_restore(flags); +} + +void local_flush_tlb_mm(struct mm_struct *mm) +{ + unsigned long flags; + unsigned int cpu = smp_processor_id(); + + if (cpu_context(cpu, mm) == NO_CONTEXT) + return; + + local_irq_save(flags); + + cpu_context(cpu, mm) = NO_CONTEXT; + if (mm == current->mm) + activate_context(mm, cpu); + + local_irq_restore(flags); +} + +void local_flush_tlb_all(void) +{ + /* Invalidate all, including shared pages, excluding fixed TLBs */ + unsigned long flags, tlb; + + local_irq_save(flags); + + /* Flush each ITLB entry */ + for_each_itlb_entry(tlb) + __flush_tlb_slot(tlb); + + /* Flush each DTLB entry */ + for_each_dtlb_entry(tlb) + __flush_tlb_slot(tlb); + + local_irq_restore(flags); +} + +void local_flush_tlb_kernel_range(unsigned long start, unsigned long end) +{ + /* FIXME: Optimize this later.. */ + flush_tlb_all(); +} diff -puN arch/sh/tools/mach-types~git-sh arch/sh/tools/mach-types --- a/arch/sh/tools/mach-types~git-sh +++ a/arch/sh/tools/mach-types @@ -45,3 +45,4 @@ X3PROTO SH_X3PROTO MAGICPANELR2 SH_MAGIC_PANEL_R2 R2D_PLUS RTS7751R2D_PLUS R2D_1 RTS7751R2D_1 +CAYMAN SH_CAYMAN diff -puN arch/sh64/Kconfig~git-sh /dev/null --- a/arch/sh64/Kconfig +++ /dev/null @@ -1,290 +0,0 @@ -# -# For a description of the syntax of this configuration file, -# see Documentation/kbuild/kconfig-language.txt. -# - -mainmenu "Linux/SH64 Kernel Configuration" - -config SUPERH - bool - default y - -config SUPERH64 - bool - default y - -config MMU - bool - default y - -config QUICKLIST - def_bool y - -config RWSEM_GENERIC_SPINLOCK - bool - default y - -config GENERIC_FIND_NEXT_BIT - bool - default y - -config GENERIC_HWEIGHT - bool - default y - -config GENERIC_CALIBRATE_DELAY - bool - default y - -config GENERIC_HARDIRQS - bool - default y - -config GENERIC_IRQ_PROBE - bool - default y - -config RWSEM_XCHGADD_ALGORITHM - bool - -config ARCH_HAS_ILOG2_U32 - bool - default n - -config ARCH_HAS_ILOG2_U64 - bool - default n - -config ARCH_NO_VIRT_TO_BUS - def_bool y - -source init/Kconfig - -menu "System type" - -choice - prompt "SuperH system type" - default SH_SIMULATOR - -config SH_SIMULATOR - bool "Simulator" - -config SH_CAYMAN - bool "Cayman" - -config SH_HARP - bool "ST50-Harp" - -endchoice - -choice - prompt "Processor family" - default CPU_SH5 - -config CPU_SH5 - bool "SH-5" - -endchoice - -choice - prompt "Processor type" - -config CPU_SUBTYPE_SH5_101 - bool "SH5-101" - depends on CPU_SH5 - -config CPU_SUBTYPE_SH5_103 - bool "SH5-103" - depends on CPU_SH5 - -endchoice - -choice - prompt "Endianness" - default LITTLE_ENDIAN - -config LITTLE_ENDIAN - bool "Little-Endian" - -config BIG_ENDIAN - bool "Big-Endian" - -endchoice - -config SH_FPU - bool "FPU support" - default y - -config SH64_FPU_DENORM_FLUSH - depends on SH_FPU - bool "Flush floating point denorms to zero" - -choice - prompt "Page table levels" - default SH64_PGTABLE_2_LEVEL - -config SH64_PGTABLE_2_LEVEL - bool "2" - -config SH64_PGTABLE_3_LEVEL - bool "3" - -endchoice - -choice - prompt "HugeTLB page size" - depends on HUGETLB_PAGE && MMU - default HUGETLB_PAGE_SIZE_64K - -config HUGETLB_PAGE_SIZE_64K - bool "64K" - -config HUGETLB_PAGE_SIZE_1MB - bool "1MB" - -config HUGETLB_PAGE_SIZE_512MB - bool "512MB" - -endchoice - -config SH64_USER_MISALIGNED_FIXUP - bool "Fixup misaligned loads/stores occurring in user mode" - -comment "Memory options" - -config CACHED_MEMORY_OFFSET - hex "Cached Area Offset" - default "20000000" - -config MEMORY_START - hex "Physical memory start address" - default "80000000" - -config MEMORY_SIZE_IN_MB - int "Memory size (in MB)" - default "8" if SH_SIMULATOR - default "64" - -comment "Cache options" - -choice - prompt "DCache mode" - default DCACHE_DISABLED if SH_SIMULATOR - default DCACHE_WRITE_BACK - -config DCACHE_WRITE_BACK - bool "Write-back" - depends on !SH_SIMULATOR - -config DCACHE_WRITE_THROUGH - bool "Write-through" - depends on !SH_SIMULATOR - -config DCACHE_DISABLED - bool "Disabled" - -endchoice - -config ICACHE_DISABLED - bool "ICache Disabling" - -config PCIDEVICE_MEMORY_START - hex - default "C0000000" - -config DEVICE_MEMORY_START - hex - default "E0000000" - -config FLASH_MEMORY_START - hex "Flash memory/on-chip devices start address" - default "00000000" - -config PCI_BLOCK_START - hex "PCI block start address" - default "40000000" - -comment "CPU Subtype specific options" - -config SH64_ID2815_WORKAROUND - bool "Include workaround for SH5-101 cut2 silicon defect ID2815" - -comment "Misc options" - -config HEARTBEAT - bool "Heartbeat LED" - depends on SH_CAYMAN - -config HDSP253_LED - bool "Support for HDSP-253 LED" - depends on SH_CAYMAN - -config SH_DMA - tristate "DMA controller (DMAC) support" - -config PREEMPT - bool "Preemptible Kernel (EXPERIMENTAL)" - depends on EXPERIMENTAL - -source "mm/Kconfig" - -endmenu - -menu "Bus options (PCI, PCMCIA, EISA, MCA, ISA)" - -config ISA - bool - -config SBUS - bool - -config PCI - bool "PCI support" - depends on SH_CAYMAN - help - Find out whether you have a PCI motherboard. PCI is the name of a - bus system, i.e. the way the CPU talks to the other stuff inside - your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or - VESA. If you have PCI, say Y, otherwise N. - -config SH_PCIDMA_NONCOHERENT - bool "Cache and PCI noncoherent" - depends on PCI - default y - help - Enable this option if your platform does not have a CPU cache which - remains coherent with PCI DMA. It is safest to say 'Y', although you - will see better performance if you can say 'N', because the PCI DMA - code will not have to flush the CPU's caches. If you have a PCI host - bridge integrated with your SH CPU, refer carefully to the chip specs - to see if you can say 'N' here. Otherwise, leave it as 'Y'. - -source "drivers/pci/Kconfig" - -source "drivers/pcmcia/Kconfig" - -source "drivers/pci/hotplug/Kconfig" - -endmenu - -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -endmenu - -source "net/Kconfig" - -source "drivers/Kconfig" - -source "fs/Kconfig" - -source "kernel/Kconfig.instrumentation" - -source "arch/sh64/Kconfig.debug" - -source "security/Kconfig" - -source "crypto/Kconfig" - -source "lib/Kconfig" diff -puN arch/sh64/Kconfig.debug~git-sh /dev/null --- a/arch/sh64/Kconfig.debug +++ /dev/null @@ -1,33 +0,0 @@ -menu "Kernel hacking" - -source "lib/Kconfig.debug" - -config EARLY_PRINTK - bool "Early SCIF console support" - -config SH64_PROC_TLB - bool "Debug: report TLB fill/purge activity through /proc/tlb" - depends on PROC_FS - -config SH64_PROC_ASIDS - bool "Debug: report ASIDs through /proc/asids" - depends on PROC_FS - -config SH64_SR_WATCH - bool "Debug: set SR.WATCH to enable hardware watchpoints and trace" - -config POOR_MANS_STRACE - bool "Debug: enable rudimentary strace facility" - help - This option allows system calls to be traced to the console. It also - aids in detecting kernel stack underflow. It is useful for debugging - early-userland problems (e.g. init incurring fatal exceptions.) - -config SH_ALPHANUMERIC - bool "Enable debug outputs to on-board alphanumeric display" - depends on SH_CAYMAN - -config SH_NO_BSS_INIT - bool "Avoid zeroing BSS (to speed-up startup on suitable platforms)" - -endmenu diff -puN arch/sh64/Makefile~git-sh /dev/null --- a/arch/sh64/Makefile +++ /dev/null @@ -1,111 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2000, 2001 Paolo Alberelli -# Copyright (C) 2003, 2004 Paul Mundt -# -# This file is included by the global makefile so that you can add your own -# architecture-specific flags and dependencies. Remember to do have actions -# for "archclean" and "archdep" for cleaning up and making dependencies for -# this architecture -# - -cpu-y := -mb -cpu-$(CONFIG_LITTLE_ENDIAN) := -ml - -cpu-$(CONFIG_CPU_SH5) += -m5-32media-nofpu - -ifdef CONFIG_LITTLE_ENDIAN -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64' -LDFLAGS += -EL -mshlelf32_linux -else -LDFLAGS_vmlinux += --defsym 'jiffies=jiffies_64+4' -LDFLAGS += -EB -mshelf32_linux -endif - -# No requirements for endianess support from AFLAGS, 'as' always run through gcc -KBUILD_CFLAGS += $(cpu-y) - -LDFLAGS_vmlinux += --defsym phys_stext=_stext-$(CONFIG_CACHED_MEMORY_OFFSET) \ - --defsym phys_stext_shmedia=phys_stext+1 \ - -e phys_stext_shmedia - -OBJCOPYFLAGS := -O binary -R .note -R .comment -R .stab -R .stabstr -S - -# -# arch/sh64/defconfig never had any hope of being -# frequently updated, so use one that does -# -KBUILD_DEFCONFIG := cayman_defconfig - -KBUILD_IMAGE := arch/$(ARCH)/boot/zImage - -ifdef LOADADDR -LINKFLAGS += -Ttext $(word 1,$(LOADADDR)) -endif - -machine-$(CONFIG_SH_CAYMAN) := cayman -machine-$(CONFIG_SH_SIMULATOR) := sim -machine-$(CONFIG_SH_HARP) := harp - -head-y := arch/$(ARCH)/kernel/head.o arch/$(ARCH)/kernel/init_task.o - -core-y += arch/sh64/kernel/ arch/sh64/mm/ - -ifneq ($(machine-y),) -core-y += arch/sh64/mach-$(machine-y)/ -endif - -LIBGCC := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name) -libs-y += arch/$(ARCH)/lib/ $(LIBGCC) - -drivers-$(CONFIG_OPROFILE) += arch/sh64/oprofile/ - -boot := arch/$(ARCH)/boot - -zImage: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -compressed: zImage - -archclean: - $(Q)$(MAKE) $(clean)=$(boot) - -archprepare: arch/$(ARCH)/lib/syscalltab.h - -define filechk_gen-syscalltab - (set -e; \ - echo "/*"; \ - echo " * DO NOT MODIFY."; \ - echo " *"; \ - echo " * This file was generated by arch/$(ARCH)/Makefile"; \ - echo " * Any changes will be reverted at build time."; \ - echo " */"; \ - echo ""; \ - echo "#ifndef __SYSCALLTAB_H"; \ - echo "#define __SYSCALLTAB_H"; \ - echo ""; \ - echo "#include "; \ - echo ""; \ - echo "struct syscall_info {"; \ - echo " const char *name;"; \ - echo "} syscall_info_table[] = {"; \ - sed -e '/^.*\.long /!d;s// { "/;s/\(\([^/]*\)\/\)\{1\}.*/\2/; \ - s/[ \t]*$$//g;s/$$/" },/;s/\("\)sys_/\1/g'; \ - echo "};"; \ - echo ""; \ - echo "#define NUM_SYSCALL_INFO_ENTRIES ARRAY_SIZE(syscall_info_table)"; \ - echo ""; \ - echo "#endif /* __SYSCALLTAB_H */" ) -endef - -arch/$(ARCH)/lib/syscalltab.h: arch/sh64/kernel/syscalls.S - $(call filechk,gen-syscalltab) - -CLEAN_FILES += arch/$(ARCH)/lib/syscalltab.h - -define archhelp - @echo '* zImage - Compressed kernel image' -endef diff -puN arch/sh64/boot/Makefile~git-sh /dev/null --- a/arch/sh64/boot/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -# -# arch/sh64/boot/Makefile -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2002 Stuart Menefy -# - -targets := zImage -subdir- := compressed - -$(obj)/zImage: $(obj)/compressed/vmlinux FORCE - $(call if_changed,objcopy) - @echo 'Kernel: $@ is ready' - -$(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ - diff -puN arch/sh64/boot/compressed/Makefile~git-sh /dev/null --- a/arch/sh64/boot/compressed/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# linux/arch/sh64/boot/compressed/Makefile -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2002 Stuart Menefy -# Copyright (C) 2004 Paul Mundt -# -# create a compressed vmlinux image from the original vmlinux -# - -targets := vmlinux vmlinux.bin vmlinux.bin.gz \ - head.o misc.o cache.o piggy.o vmlinux.lds - -EXTRA_AFLAGS := -traditional - -OBJECTS := $(obj)/head.o $(obj)/misc.o $(obj)/cache.o - -# -# ZIMAGE_OFFSET is the load offset of the compression loader -# (4M for the kernel plus 64K for this loader) -# -ZIMAGE_OFFSET = $(shell printf "0x%8x" $$[$(CONFIG_MEMORY_START)+0x400000+0x10000]) - -LDFLAGS_vmlinux := -Ttext $(ZIMAGE_OFFSET) -e startup \ - -T $(obj)/../../kernel/vmlinux.lds \ - --no-warn-mismatch - -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o FORCE - $(call if_changed,ld) - @: - -$(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/vmlinux.bin.gz: $(obj)/vmlinux.bin FORCE - $(call if_changed,gzip) - -LDFLAGS_piggy.o := -r --format binary --oformat elf32-sh64-linux -T -OBJCOPYFLAGS += -R .empty_zero_page - -$(obj)/piggy.o: $(obj)/vmlinux.lds $(obj)/vmlinux.bin.gz FORCE - $(call if_changed,ld) - diff -puN arch/sh64/boot/compressed/cache.c~git-sh /dev/null --- a/arch/sh64/boot/compressed/cache.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * arch/shmedia/boot/compressed/cache.c -- simple cache management functions - * - * Code extracted from sh-ipl+g, sh-stub.c, which has the copyright: - * - * This is originally based on an m68k software stub written by Glenn - * Engel at HP, but has changed quite a bit. - * - * Modifications for the SH by Ben Lee and Steve Chamberlain - * -**************************************************************************** - - THIS SOFTWARE IS NOT COPYRIGHTED - - HP offers the following for use in the public domain. HP makes no - warranty with regard to the software or it's performance and the - user accepts the software "AS IS" with all faults. - - HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD - TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES - OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - -****************************************************************************/ - -#define CACHE_ENABLE 0 -#define CACHE_DISABLE 1 - -int cache_control(unsigned int command) -{ - volatile unsigned int *p = (volatile unsigned int *) 0x80000000; - int i; - - for (i = 0; i < (32 * 1024); i += 32) { - (void *) *p; - p += (32 / sizeof (int)); - } - - return 0; -} diff -puN arch/sh64/boot/compressed/head.S~git-sh /dev/null --- a/arch/sh64/boot/compressed/head.S +++ /dev/null @@ -1,164 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/shmedia/boot/compressed/head.S - * - * Copied from - * arch/shmedia/kernel/head.S - * which carried the copyright: - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * Modification for compressed loader: - * Copyright (C) 2002 Stuart Menefy (stuart.menefy@st.com) - */ - -#include -#include -#include -#include - -/* - * Fixed TLB entries to identity map the beginning of RAM - */ -#define MMUIR_TEXT_H 0x0000000000000003 | CONFIG_MEMORY_START - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ -#define MMUIR_TEXT_L 0x000000000000009a | CONFIG_MEMORY_START - /* 512 Mb, Cacheable (Write-back), execute, Not User, Ph. Add. */ - -#define MMUDR_CACHED_H 0x0000000000000003 | CONFIG_MEMORY_START - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ -#define MMUDR_CACHED_L 0x000000000000015a | CONFIG_MEMORY_START - /* 512 Mb, Cacheable (Write-back), read/write, Not User, Ph. Add. */ - -#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */ -#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */ - -#if 1 -#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* OCE + OCI + WB */ -#else -#define OCCR0_INIT_VAL OCCR0_OFF -#endif -#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */ - - .text - - .global startup -startup: - /* - * Prevent speculative fetch on device memory due to - * uninitialized target registers. - * This must be executed before the first branch. - */ - ptabs/u ZERO, tr0 - ptabs/u ZERO, tr1 - ptabs/u ZERO, tr2 - ptabs/u ZERO, tr3 - ptabs/u ZERO, tr4 - ptabs/u ZERO, tr5 - ptabs/u ZERO, tr6 - ptabs/u ZERO, tr7 - synci - - /* - * Set initial TLB entries for cached and uncached regions. - * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! - */ - /* Clear ITLBs */ - pta 1f, tr1 - movi ITLB_FIXED, r21 - movi ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22 -1: putcfg r21, 0, ZERO /* Clear MMUIR[n].PTEH.V */ - addi r21, TLB_STEP, r21 - bne r21, r22, tr1 - - /* Clear DTLBs */ - pta 1f, tr1 - movi DTLB_FIXED, r21 - movi DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP, r22 -1: putcfg r21, 0, ZERO /* Clear MMUDR[n].PTEH.V */ - addi r21, TLB_STEP, r21 - bne r21, r22, tr1 - - /* Map one big (512Mb) page for ITLB */ - movi ITLB_FIXED, r21 - movi MMUIR_TEXT_L, r22 /* PTEL first */ - putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */ - movi MMUIR_TEXT_H, r22 /* PTEH last */ - putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */ - - /* Map one big CACHED (512Mb) page for DTLB */ - movi DTLB_FIXED, r21 - movi MMUDR_CACHED_L, r22 /* PTEL first */ - putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */ - movi MMUDR_CACHED_H, r22 /* PTEH last */ - putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ - - /* ICache */ - movi ICCR_BASE, r21 - movi ICCR0_INIT_VAL, r22 - movi ICCR1_INIT_VAL, r23 - putcfg r21, ICCR_REG0, r22 - putcfg r21, ICCR_REG1, r23 - synci - - /* OCache */ - movi OCCR_BASE, r21 - movi OCCR0_INIT_VAL, r22 - movi OCCR1_INIT_VAL, r23 - putcfg r21, OCCR_REG0, r22 - putcfg r21, OCCR_REG1, r23 - synco - - /* - * Enable the MMU. - * From here-on code can be non-PIC. - */ - movi SR_HARMLESS | SR_ENABLE_MMU, r22 - putcon r22, SSR - movi 1f, r22 - putcon r22, SPC - synco - rte /* And now go into the hyperspace ... */ -1: /* ... that's the next instruction ! */ - - /* Set initial stack pointer */ - movi datalabel stack_start, r0 - ld.l r0, 0, r15 - - /* - * Clear bss - */ - pt 1f, tr1 - movi datalabel __bss_start, r22 - movi datalabel _end, r23 -1: st.l r22, 0, ZERO - addi r22, 4, r22 - bne r22, r23, tr1 - - /* - * Decompress the kernel. - */ - pt decompress_kernel, tr0 - blink tr0, r18 - - /* - * Disable the MMU. - */ - movi SR_HARMLESS, r22 - putcon r22, SSR - movi 1f, r22 - putcon r22, SPC - synco - rte /* And now go into the hyperspace ... */ -1: /* ... that's the next instruction ! */ - - /* Jump into the decompressed kernel */ - movi datalabel (CONFIG_MEMORY_START + 0x2000)+1, r19 - ptabs r19, tr0 - blink tr0, r18 - - /* Shouldn't return here, but just in case, loop forever */ - pt 1f, tr0 -1: blink tr0, ZERO diff -puN arch/sh64/boot/compressed/install.sh~git-sh /dev/null --- a/arch/sh64/boot/compressed/install.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/sh -# -# arch/sh/boot/install.sh -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 1995 by Linus Torvalds -# -# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin -# Adapted from code in arch/i386/boot/install.sh by Russell King -# Adapted from code in arch/arm/boot/install.sh by Stuart Menefy -# -# "make install" script for sh architecture -# -# Arguments: -# $1 - kernel version -# $2 - kernel image file -# $3 - kernel map file -# $4 - default install path (blank if root directory) -# - -# User may have a custom install script - -if [ -x /sbin/installkernel ]; then - exec /sbin/installkernel "$@" -fi - -if [ "$2" = "zImage" ]; then -# Compressed install - echo "Installing compressed kernel" - if [ -f $4/vmlinuz-$1 ]; then - mv $4/vmlinuz-$1 $4/vmlinuz.old - fi - - if [ -f $4/System.map-$1 ]; then - mv $4/System.map-$1 $4/System.old - fi - - cat $2 > $4/vmlinuz-$1 - cp $3 $4/System.map-$1 -else -# Normal install - echo "Installing normal kernel" - if [ -f $4/vmlinux-$1 ]; then - mv $4/vmlinux-$1 $4/vmlinux.old - fi - - if [ -f $4/System.map ]; then - mv $4/System.map $4/System.old - fi - - cat $2 > $4/vmlinux-$1 - cp $3 $4/System.map -fi diff -puN arch/sh64/boot/compressed/misc.c~git-sh /dev/null --- a/arch/sh64/boot/compressed/misc.c +++ /dev/null @@ -1,250 +0,0 @@ -/* - * arch/sh64/boot/compressed/misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * - * Adapted for SHmedia from sh by Stuart Menefy, May 2002 - */ - -#include - -/* cache.c */ -#define CACHE_ENABLE 0 -#define CACHE_DISABLE 1 -int cache_control(unsigned int command); - -/* - * gzip declarations - */ - -#define OF(args) args -#define STATIC static - -#undef memset -#undef memcpy -#define memzero(s, n) memset ((s), 0, (n)) - -typedef unsigned char uch; -typedef unsigned short ush; -typedef unsigned long ulg; - -#define WSIZE 0x8000 /* Window size must be at least 32k, */ - /* and a power of two */ - -static uch *inbuf; /* input buffer */ -static uch window[WSIZE]; /* Sliding window buffer */ - -static unsigned insize = 0; /* valid bytes in inbuf */ -static unsigned inptr = 0; /* index of next byte to be processed in inbuf */ -static unsigned outcnt = 0; /* bytes in output buffer */ - -/* gzip flag byte */ -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */ -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ -#define COMMENT 0x10 /* bit 4 set: file comment present */ -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ -#define RESERVED 0xC0 /* bit 6,7: reserved */ - -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) - -/* Diagnostic functions */ -#ifdef DEBUG -# define Assert(cond,msg) {if(!(cond)) error(msg);} -# define Trace(x) fprintf x -# define Tracev(x) {if (verbose) fprintf x ;} -# define Tracevv(x) {if (verbose>1) fprintf x ;} -# define Tracec(c,x) {if (verbose && (c)) fprintf x ;} -# define Tracecv(c,x) {if (verbose>1 && (c)) fprintf x ;} -#else -# define Assert(cond,msg) -# define Trace(x) -# define Tracev(x) -# define Tracevv(x) -# define Tracec(c,x) -# define Tracecv(c,x) -#endif - -static int fill_inbuf(void); -static void flush_window(void); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -extern char input_data[]; -extern int input_len; - -static long bytes_out = 0; -static uch *output_data; -static unsigned long output_ptr = 0; - -static void *malloc(int size); -static void free(void *where); -static void error(char *m); -static void gzip_mark(void **); -static void gzip_release(void **); - -static void puts(const char *); - -extern int _text; /* Defined in vmlinux.lds.S */ -extern int _end; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -#define HEAP_SIZE 0x10000 - -#include "../../../../lib/inflate.c" - -static void *malloc(int size) -{ - void *p; - - if (size < 0) - error("Malloc error\n"); - if (free_mem_ptr == 0) - error("Memory error\n"); - - free_mem_ptr = (free_mem_ptr + 3) & ~3; /* Align */ - - p = (void *) free_mem_ptr; - free_mem_ptr += size; - - if (free_mem_ptr >= free_mem_end_ptr) - error("\nOut of memory\n"); - - return p; -} - -static void free(void *where) -{ /* Don't care */ -} - -static void gzip_mark(void **ptr) -{ - *ptr = (void *) free_mem_ptr; -} - -static void gzip_release(void **ptr) -{ - free_mem_ptr = (long) *ptr; -} - -void puts(const char *s) -{ -} - -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = (char *) s; - - for (i = 0; i < n; i++) - ss[i] = c; - return s; -} - -void *memcpy(void *__dest, __const void *__src, size_t __n) -{ - int i; - char *d = (char *) __dest, *s = (char *) __src; - - for (i = 0; i < __n; i++) - d[i] = s[i]; - return __dest; -} - -/* =========================================================================== - * Fill the input buffer. This is called only when the buffer is empty - * and at least one byte is really needed. - */ -static int fill_inbuf(void) -{ - if (insize != 0) { - error("ran out of input data\n"); - } - - inbuf = input_data; - insize = input_len; - inptr = 1; - return inbuf[0]; -} - -/* =========================================================================== - * Write the output window window[0..outcnt-1] and update crc and bytes_out. - * (Used for the decompressed data only.) - */ -static void flush_window(void) -{ - ulg c = crc; /* temporary variable */ - unsigned n; - uch *in, *out, ch; - - in = window; - out = &output_data[output_ptr]; - for (n = 0; n < outcnt; n++) { - ch = *out++ = *in++; - c = crc_32_tab[((int) c ^ ch) & 0xff] ^ (c >> 8); - } - crc = c; - bytes_out += (ulg) outcnt; - output_ptr += (ulg) outcnt; - outcnt = 0; - puts("."); -} - -static void error(char *x) -{ - puts("\n\n"); - puts(x); - puts("\n\n -- System halted"); - - while (1) ; /* Halt */ -} - -#define STACK_SIZE (4096) -long __attribute__ ((aligned(8))) user_stack[STACK_SIZE]; -long *stack_start = &user_stack[STACK_SIZE]; - -void decompress_kernel(void) -{ - output_data = (uch *) (CONFIG_MEMORY_START + 0x2000); - free_mem_ptr = (unsigned long) &_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - - makecrc(); - puts("Uncompressing Linux... "); - cache_control(CACHE_ENABLE); - gunzip(); - puts("\n"); - -#if 0 - /* When booting from ROM may want to do something like this if the - * boot loader doesn't. - */ - - /* Set up the parameters and command line */ - { - volatile unsigned int *parambase = - (int *) (CONFIG_MEMORY_START + 0x1000); - - parambase[0] = 0x1; /* MOUNT_ROOT_RDONLY */ - parambase[1] = 0x0; /* RAMDISK_FLAGS */ - parambase[2] = 0x0200; /* ORIG_ROOT_DEV */ - parambase[3] = 0x0; /* LOADER_TYPE */ - parambase[4] = 0x0; /* INITRD_START */ - parambase[5] = 0x0; /* INITRD_SIZE */ - parambase[6] = 0; - - strcpy((char *) ((int) parambase + 0x100), - "console=ttySC0,38400"); - } -#endif - - puts("Ok, booting the kernel.\n"); - - cache_control(CACHE_DISABLE); -} diff -puN arch/sh64/boot/compressed/vmlinux.lds.S~git-sh /dev/null --- a/arch/sh64/boot/compressed/vmlinux.lds.S +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ld script to make compressed SuperH/shmedia Linux kernel+decompression - * bootstrap - * Modified by Stuart Menefy from arch/sh/vmlinux.lds.S written by Niibe Yutaka - */ - - -#ifdef CONFIG_LITTLE_ENDIAN -/* OUTPUT_FORMAT("elf32-sh64l-linux", "elf32-sh64l-linux", "elf32-sh64l-linux") */ -#define NOP 0x6ff0fff0 -#else -/* OUTPUT_FORMAT("elf32-sh64", "elf32-sh64", "elf32-sh64") */ -#define NOP 0xf0fff06f -#endif - -OUTPUT_FORMAT("elf32-sh64-linux") -OUTPUT_ARCH(sh) -ENTRY(_start) - -#define ALIGNED_GAP(section, align) (((ADDR(section)+SIZEOF(section)+(align)-1) & ~((align)-1))-ADDR(section)) -#define FOLLOWING(section, align) AT (LOADADDR(section) + ALIGNED_GAP(section,align)) - -SECTIONS -{ - _text = .; /* Text and read-only data */ - - .text : { - *(.text) - *(.text64) - *(.text..SHmedia32) - *(.fixup) - *(.gnu.warning) - } = NOP - . = ALIGN(4); - .rodata : { *(.rodata) } - - /* There is no 'real' reason for eight byte alignment, four would work - * as well, but gdb downloads much (*4) faster with this. - */ - . = ALIGN(8); - .image : { *(.image) } - . = ALIGN(4); - _etext = .; /* End of text section */ - - .data : /* Data */ - FOLLOWING(.image, 4) - { - _data = .; - *(.data) - } - _data_image = LOADADDR(.data);/* Address of data section in ROM */ - - _edata = .; /* End of data section */ - - .stack : { stack = .; _stack = .; } - - . = ALIGN(4); - __bss_start = .; /* BSS */ - .bss : { - *(.bss) - } - . = ALIGN(4); - _end = . ; -} diff -puN arch/sh64/configs/cayman_defconfig~git-sh /dev/null --- a/arch/sh64/configs/cayman_defconfig +++ /dev/null @@ -1,1126 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc1 -# Fri Nov 2 14:35:27 2007 -# -CONFIG_SUPERH=y -CONFIG_SUPERH64=y -CONFIG_MMU=y -CONFIG_QUICKLIST=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -# CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -CONFIG_MODULES=y -CONFIG_MODULE_UNLOAD=y -# CONFIG_MODULE_FORCE_UNLOAD is not set -# CONFIG_MODVERSIONS is not set -# CONFIG_MODULE_SRCVERSION_ALL is not set -CONFIG_KMOD=y -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - -# -# System type -# -# CONFIG_SH_SIMULATOR is not set -CONFIG_SH_CAYMAN=y -# CONFIG_SH_HARP is not set -CONFIG_CPU_SH5=y -CONFIG_CPU_SUBTYPE_SH5_101=y -# CONFIG_CPU_SUBTYPE_SH5_103 is not set -CONFIG_LITTLE_ENDIAN=y -# CONFIG_BIG_ENDIAN is not set -CONFIG_SH_FPU=y -# CONFIG_SH64_FPU_DENORM_FLUSH is not set -CONFIG_SH64_PGTABLE_2_LEVEL=y -# CONFIG_SH64_PGTABLE_3_LEVEL is not set -CONFIG_HUGETLB_PAGE_SIZE_64K=y -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set -CONFIG_SH64_USER_MISALIGNED_FIXUP=y - -# -# Memory options -# -CONFIG_CACHED_MEMORY_OFFSET=0x20000000 -CONFIG_MEMORY_START=0x80000000 -CONFIG_MEMORY_SIZE_IN_MB=128 - -# -# Cache options -# -CONFIG_DCACHE_WRITE_BACK=y -# CONFIG_DCACHE_WRITE_THROUGH is not set -# CONFIG_DCACHE_DISABLED is not set -# CONFIG_ICACHE_DISABLED is not set -CONFIG_PCIDEVICE_MEMORY_START=C0000000 -CONFIG_DEVICE_MEMORY_START=E0000000 -CONFIG_FLASH_MEMORY_START=0x00000000 -CONFIG_PCI_BLOCK_START=0x40000000 - -# -# CPU Subtype specific options -# -CONFIG_SH64_ID2815_WORKAROUND=y - -# -# Misc options -# -CONFIG_HEARTBEAT=y -CONFIG_HDSP253_LED=y -# CONFIG_SH_DMA is not set -CONFIG_PREEMPT=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=1 - -# -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) -# -CONFIG_PCI=y -CONFIG_SH_PCIDMA_NONCOHERENT=y -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCI_DEBUG is not set -# CONFIG_PCCARD is not set -# CONFIG_HOTPLUG_PCI is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=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_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# 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=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_SX8 is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -CONFIG_MISC_DEVICES=y -# CONFIG_PHANTOM is not set -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_SGI_IOC4 is not set -# CONFIG_TIFM_CORE is not set -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set -CONFIG_SCSI_WAIT_SCAN=m - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_BLK_DEV_3W_XXXX_RAID is not set -# CONFIG_SCSI_3W_9XXX is not set -# CONFIG_SCSI_ACARD is not set -# CONFIG_SCSI_AACRAID is not set -# CONFIG_SCSI_AIC7XXX is not set -# CONFIG_SCSI_AIC7XXX_OLD is not set -# CONFIG_SCSI_AIC79XX is not set -# CONFIG_SCSI_AIC94XX is not set -# CONFIG_SCSI_ARCMSR is not set -# CONFIG_MEGARAID_NEWGEN is not set -# CONFIG_MEGARAID_LEGACY is not set -# CONFIG_MEGARAID_SAS is not set -# CONFIG_SCSI_HPTIOP is not set -# CONFIG_SCSI_DMX3191D is not set -# CONFIG_SCSI_FUTURE_DOMAIN is not set -# CONFIG_SCSI_IPS is not set -# CONFIG_SCSI_INITIO is not set -# CONFIG_SCSI_INIA100 is not set -# CONFIG_SCSI_STEX is not set -CONFIG_SCSI_SYM53C8XX_2=y -CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 -CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 -CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -CONFIG_SCSI_SYM53C8XX_MMIO=y -# CONFIG_SCSI_QLOGIC_1280 is not set -# CONFIG_SCSI_QLA_FC is not set -# CONFIG_SCSI_QLA_ISCSI is not set -# CONFIG_SCSI_LPFC is not set -# CONFIG_SCSI_DC395x is not set -# CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_SCSI_SRP is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_FUSION is not set - -# -# IEEE 1394 (FireWire) support -# -# CONFIG_FIREWIRE is not set -# CONFIG_IEEE1394 is not set -# CONFIG_I2O is not set -CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set -# CONFIG_IP1000 is not set -# CONFIG_ARCNET is not set -# CONFIG_PHYLIB is not set -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_STNIC is not set -# CONFIG_HAPPYMEAL is not set -# CONFIG_SUNGEM is not set -# CONFIG_CASSINI is not set -# CONFIG_NET_VENDOR_3COM is not set -# CONFIG_SMC91X is not set -# CONFIG_SMC911X is not set -CONFIG_NET_TULIP=y -# CONFIG_DE2104X is not set -CONFIG_TULIP=y -# CONFIG_TULIP_MWI is not set -# CONFIG_TULIP_MMIO is not set -# CONFIG_TULIP_NAPI is not set -# CONFIG_DE4X5 is not set -# CONFIG_WINBOND_840 is not set -# CONFIG_DM9102 is not set -# CONFIG_ULI526X is not set -# CONFIG_HP100 is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 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_EEPRO100 is not set -# CONFIG_E100 is not set -# CONFIG_FEALNX is not set -# CONFIG_NATSEMI is not set -# CONFIG_NE2K_PCI is not set -# 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 -# CONFIG_SC92031 is not set -CONFIG_NETDEV_1000=y -# CONFIG_ACENIC is not set -# CONFIG_DL2K is not set -# CONFIG_E1000 is not set -# CONFIG_E1000E is not set -# CONFIG_NS83820 is not set -# CONFIG_HAMACHI is not set -# CONFIG_YELLOWFIN is not set -# CONFIG_R8169 is not set -# CONFIG_SIS190 is not set -# CONFIG_SKGE is not set -# CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set -# CONFIG_VIA_VELOCITY is not set -# CONFIG_TIGON3 is not set -# CONFIG_BNX2 is not set -# CONFIG_QLA3XXX is not set -# CONFIG_ATL1 is not set -CONFIG_NETDEV_10000=y -# CONFIG_CHELSIO_T1 is not set -# CONFIG_CHELSIO_T3 is not set -# CONFIG_IXGBE is not set -# CONFIG_IXGB is not set -# CONFIG_S2IO is not set -# CONFIG_MYRI10GE is not set -# CONFIG_NETXEN_NIC is not set -# CONFIG_NIU is not set -# CONFIG_MLX4_CORE is not set -# CONFIG_TEHUTI is not set -# CONFIG_TR is not set - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set -# 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_NET_FC is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -CONFIG_INPUT_MOUSEDEV_PSAUX=y -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -CONFIG_INPUT_KEYBOARD=y -CONFIG_KEYBOARD_ATKBD=y -# CONFIG_KEYBOARD_SUNKBD is not set -# CONFIG_KEYBOARD_LKKBD is not set -# CONFIG_KEYBOARD_XTKBD is not set -# CONFIG_KEYBOARD_NEWTON is not set -# CONFIG_KEYBOARD_STOWAWAY is not set -CONFIG_INPUT_MOUSE=y -CONFIG_MOUSE_PS2=y -CONFIG_MOUSE_PS2_ALPS=y -CONFIG_MOUSE_PS2_LOGIPS2PP=y -CONFIG_MOUSE_PS2_SYNAPTICS=y -CONFIG_MOUSE_PS2_LIFEBOOK=y -CONFIG_MOUSE_PS2_TRACKPOINT=y -# CONFIG_MOUSE_PS2_TOUCHKIT is not set -# CONFIG_MOUSE_SERIAL is not set -# CONFIG_MOUSE_APPLETOUCH is not set -# CONFIG_MOUSE_VSXXXAA is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -CONFIG_SERIO=y -CONFIG_SERIO_I8042=y -CONFIG_SERIO_SERPORT=y -# CONFIG_SERIO_PCIPS2 is not set -CONFIG_SERIO_LIBPS2=y -# CONFIG_SERIO_RAW is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=2 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -# CONFIG_SERIAL_JSM is not set -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=y -# CONFIG_R3964 is not set -# CONFIG_APPLICOM is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -CONFIG_DEVPORT=y -CONFIG_I2C=m -CONFIG_I2C_BOARDINFO=y -# CONFIG_I2C_CHARDEV is not set - -# -# I2C Algorithms -# -# CONFIG_I2C_ALGOBIT is not set -# CONFIG_I2C_ALGOPCF is not set -# CONFIG_I2C_ALGOPCA is not set - -# -# I2C Hardware Bus support -# -# CONFIG_I2C_ALI1535 is not set -# CONFIG_I2C_ALI1563 is not set -# CONFIG_I2C_ALI15X3 is not set -# CONFIG_I2C_AMD756 is not set -# CONFIG_I2C_AMD8111 is not set -# CONFIG_I2C_I801 is not set -# CONFIG_I2C_I810 is not set -# CONFIG_I2C_PIIX4 is not set -# CONFIG_I2C_NFORCE2 is not set -# CONFIG_I2C_OCORES is not set -# CONFIG_I2C_PARPORT_LIGHT is not set -# CONFIG_I2C_PROSAVAGE is not set -# CONFIG_I2C_SAVAGE4 is not set -# CONFIG_I2C_SIMTEC is not set -# CONFIG_I2C_SIS5595 is not set -# CONFIG_I2C_SIS630 is not set -# CONFIG_I2C_SIS96X is not set -# CONFIG_I2C_TAOS_EVM is not set -# CONFIG_I2C_STUB is not set -# CONFIG_I2C_VIA is not set -# CONFIG_I2C_VIAPRO is not set -# CONFIG_I2C_VOODOO3 is not set - -# -# Miscellaneous I2C Chip support -# -# CONFIG_SENSORS_DS1337 is not set -# CONFIG_SENSORS_DS1374 is not set -# CONFIG_DS1682 is not set -# CONFIG_SENSORS_EEPROM is not set -# CONFIG_SENSORS_PCF8574 is not set -# CONFIG_SENSORS_PCA9539 is not set -# CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_MAX6875 is not set -# CONFIG_SENSORS_TSL2550 is not set -# CONFIG_I2C_DEBUG_CORE is not set -# CONFIG_I2C_DEBUG_ALGO is not set -# CONFIG_I2C_DEBUG_BUS is not set -# CONFIG_I2C_DEBUG_CHIP is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_AD7418 is not set -# CONFIG_SENSORS_ADM1021 is not set -# CONFIG_SENSORS_ADM1025 is not set -# CONFIG_SENSORS_ADM1026 is not set -# CONFIG_SENSORS_ADM1029 is not set -# CONFIG_SENSORS_ADM1031 is not set -# CONFIG_SENSORS_ADM9240 is not set -# CONFIG_SENSORS_ADT7470 is not set -# CONFIG_SENSORS_ATXP1 is not set -# CONFIG_SENSORS_DS1621 is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_F75375S is not set -# CONFIG_SENSORS_GL518SM is not set -# CONFIG_SENSORS_GL520SM is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_LM63 is not set -# CONFIG_SENSORS_LM75 is not set -# CONFIG_SENSORS_LM77 is not set -# CONFIG_SENSORS_LM78 is not set -# CONFIG_SENSORS_LM80 is not set -# CONFIG_SENSORS_LM83 is not set -# CONFIG_SENSORS_LM85 is not set -# CONFIG_SENSORS_LM87 is not set -# CONFIG_SENSORS_LM90 is not set -# CONFIG_SENSORS_LM92 is not set -# CONFIG_SENSORS_LM93 is not set -# CONFIG_SENSORS_MAX1619 is not set -# CONFIG_SENSORS_MAX6650 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_SIS5595 is not set -# CONFIG_SENSORS_DME1737 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47M192 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_THMC50 is not set -# CONFIG_SENSORS_VIA686A is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_VT8231 is not set -# CONFIG_SENSORS_W83781D is not set -# CONFIG_SENSORS_W83791D is not set -# CONFIG_SENSORS_W83792D is not set -# CONFIG_SENSORS_W83793 is not set -# CONFIG_SENSORS_W83L785TS is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set - -# -# PCI-based Watchdog Cards -# -# CONFIG_PCIPCWATCHDOG is not set -# CONFIG_WDTPCI is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - -# -# Multimedia devices -# -CONFIG_VIDEO_DEV=m -# CONFIG_VIDEO_V4L1 is not set -# CONFIG_VIDEO_V4L1_COMPAT is not set -CONFIG_VIDEO_V4L2=y -CONFIG_VIDEO_CAPTURE_DRIVERS=y -# CONFIG_VIDEO_ADV_DEBUG is not set -CONFIG_VIDEO_HELPER_CHIPS_AUTO=y -# CONFIG_VIDEO_VIVI is not set -# CONFIG_VIDEO_SAA5246A is not set -# CONFIG_VIDEO_SAA5249 is not set -# CONFIG_VIDEO_SAA7134 is not set -# CONFIG_VIDEO_HEXIUM_ORION is not set -# CONFIG_VIDEO_HEXIUM_GEMINI is not set -# CONFIG_VIDEO_CX88 is not set -# CONFIG_VIDEO_CX23885 is not set -# CONFIG_VIDEO_CAFE_CCIC is not set -# CONFIG_RADIO_ADAPTERS is not set -CONFIG_DVB_CORE=y -# CONFIG_DVB_CORE_ATTACH is not set -CONFIG_DVB_CAPTURE_DRIVERS=y - -# -# Supported SAA7146 based PCI Adapters -# - -# -# Supported FlexCopII (B2C2) Adapters -# -# CONFIG_DVB_B2C2_FLEXCOP is not set - -# -# Supported BT878 Adapters -# - -# -# Supported Pluto2 Adapters -# -# CONFIG_DVB_PLUTO2 is not set - -# -# Supported DVB Frontends -# - -# -# Customise DVB Frontends -# -# CONFIG_DVB_FE_CUSTOMISE is not set - -# -# DVB-S (satellite) frontends -# -# CONFIG_DVB_STV0299 is not set -# CONFIG_DVB_CX24110 is not set -# CONFIG_DVB_CX24123 is not set -# CONFIG_DVB_TDA8083 is not set -# CONFIG_DVB_MT312 is not set -# CONFIG_DVB_VES1X93 is not set -# CONFIG_DVB_S5H1420 is not set -# CONFIG_DVB_TDA10086 is not set - -# -# DVB-T (terrestrial) frontends -# -# CONFIG_DVB_SP8870 is not set -# CONFIG_DVB_SP887X is not set -# CONFIG_DVB_CX22700 is not set -# CONFIG_DVB_CX22702 is not set -# CONFIG_DVB_L64781 is not set -# CONFIG_DVB_TDA1004X is not set -# CONFIG_DVB_NXT6000 is not set -# CONFIG_DVB_MT352 is not set -# CONFIG_DVB_ZL10353 is not set -# CONFIG_DVB_DIB3000MB is not set -# CONFIG_DVB_DIB3000MC is not set -# CONFIG_DVB_DIB7000M is not set -# CONFIG_DVB_DIB7000P is not set - -# -# DVB-C (cable) frontends -# -# CONFIG_DVB_VES1820 is not set -# CONFIG_DVB_TDA10021 is not set -# CONFIG_DVB_TDA10023 is not set -# CONFIG_DVB_STV0297 is not set - -# -# ATSC (North American/Korean Terrestrial/Cable DTV) frontends -# -# CONFIG_DVB_NXT200X is not set -# CONFIG_DVB_OR51211 is not set -# CONFIG_DVB_OR51132 is not set -# CONFIG_DVB_BCM3510 is not set -# CONFIG_DVB_LGDT330X is not set -# CONFIG_DVB_S5H1409 is not set - -# -# Tuners/PLL support -# -# CONFIG_DVB_PLL is not set -# CONFIG_DVB_TDA826X is not set -# CONFIG_DVB_TDA827X is not set -# CONFIG_DVB_TUNER_QT1010 is not set -# CONFIG_DVB_TUNER_MT2060 is not set -# CONFIG_DVB_TUNER_MT2266 is not set -# CONFIG_DVB_TUNER_MT2131 is not set -# CONFIG_DVB_TUNER_DIB0070 is not set - -# -# Miscellaneous devices -# -# CONFIG_DVB_LNBP21 is not set -# CONFIG_DVB_ISL6421 is not set -# CONFIG_DVB_TUA6100 is not set -CONFIG_DAB=y - -# -# Graphics support -# -# CONFIG_DRM is not set -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB_DDC is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_CIRRUS is not set -# CONFIG_FB_PM2 is not set -# CONFIG_FB_CYBER2000 is not set -# CONFIG_FB_ASILIANT is not set -# CONFIG_FB_IMSTT is not set -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_NVIDIA is not set -# CONFIG_FB_RIVA is not set -# CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON is not set -# CONFIG_FB_ATY128 is not set -# CONFIG_FB_ATY is not set -# CONFIG_FB_S3 is not set -# CONFIG_FB_SAVAGE is not set -# CONFIG_FB_SIS is not set -# CONFIG_FB_NEOMAGIC is not set -CONFIG_FB_KYRO=y -# CONFIG_FB_3DFX is not set -# CONFIG_FB_VOODOO1 is not set -# CONFIG_FB_VT8623 is not set -# CONFIG_FB_TRIDENT is not set -# CONFIG_FB_ARK is not set -# CONFIG_FB_PM3 is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_LOGO_SUPERH_MONO is not set -# CONFIG_LOGO_SUPERH_VGA16 is not set -CONFIG_LOGO_SUPERH_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HID_DEBUG is not set -# CONFIG_HIDRAW is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -CONFIG_USB_ARCH_HAS_OHCI=y -CONFIG_USB_ARCH_HAS_EHCI=y -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set -# CONFIG_MMC is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_INFINIBAND is not set -# CONFIG_RTC_CLASS is not set - -# -# Userspace I/O -# -# CONFIG_UIO is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -CONFIG_MINIX_FS=y -CONFIG_ROMFS_FS=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS 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=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL 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_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set -# 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=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_NLS is not set -# CONFIG_DLM is not set -CONFIG_INSTRUMENTATION=y -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y -CONFIG_SCHEDSTATS=y -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_RCU_TORTURE_TEST is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -# CONFIG_EARLY_PRINTK is not set -CONFIG_SH64_PROC_TLB=y -CONFIG_SH64_PROC_ASIDS=y -CONFIG_SH64_SR_WATCH=y -# CONFIG_POOR_MANS_STRACE is not set -# CONFIG_SH_ALPHANUMERIC is not set -# CONFIG_SH_NO_BSS_INIT is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff -puN arch/sh64/configs/harp_defconfig~git-sh /dev/null --- a/arch/sh64/configs/harp_defconfig +++ /dev/null @@ -1,745 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc1 -# Fri Nov 2 14:35:57 2007 -# -CONFIG_SUPERH=y -CONFIG_SUPERH64=y -CONFIG_MMU=y -CONFIG_QUICKLIST=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -CONFIG_POSIX_MQUEUE=y -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set -# CONFIG_AUDIT is not set -# CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -# CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_MODULES is not set -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - -# -# System type -# -# CONFIG_SH_SIMULATOR is not set -# CONFIG_SH_CAYMAN is not set -CONFIG_SH_HARP=y -CONFIG_CPU_SH5=y -CONFIG_CPU_SUBTYPE_SH5_101=y -# CONFIG_CPU_SUBTYPE_SH5_103 is not set -CONFIG_LITTLE_ENDIAN=y -# CONFIG_BIG_ENDIAN is not set -CONFIG_SH_FPU=y -# CONFIG_SH64_FPU_DENORM_FLUSH is not set -CONFIG_SH64_PGTABLE_2_LEVEL=y -# CONFIG_SH64_PGTABLE_3_LEVEL is not set -CONFIG_HUGETLB_PAGE_SIZE_64K=y -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set -CONFIG_SH64_USER_MISALIGNED_FIXUP=y - -# -# Memory options -# -CONFIG_CACHED_MEMORY_OFFSET=0x20000000 -CONFIG_MEMORY_START=0x80000000 -CONFIG_MEMORY_SIZE_IN_MB=128 - -# -# Cache options -# -CONFIG_DCACHE_WRITE_BACK=y -# CONFIG_DCACHE_WRITE_THROUGH is not set -# CONFIG_DCACHE_DISABLED is not set -# CONFIG_ICACHE_DISABLED is not set -CONFIG_PCIDEVICE_MEMORY_START=C0000000 -CONFIG_DEVICE_MEMORY_START=E0000000 -CONFIG_FLASH_MEMORY_START=0x00000000 -CONFIG_PCI_BLOCK_START=0x40000000 - -# -# CPU Subtype specific options -# -CONFIG_SH64_ID2815_WORKAROUND=y - -# -# Misc options -# -# CONFIG_SH_DMA is not set -CONFIG_PREEMPT=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=1 - -# -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) -# -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set - -# -# Networking -# -CONFIG_NET=y - -# -# Networking options -# -CONFIG_PACKET=y -# CONFIG_PACKET_MMAP is not set -CONFIG_UNIX=y -CONFIG_XFRM=y -# CONFIG_XFRM_USER is not set -# CONFIG_XFRM_SUB_POLICY is not set -# CONFIG_XFRM_MIGRATE is not set -# CONFIG_NET_KEY is not set -CONFIG_INET=y -# CONFIG_IP_MULTICAST is not set -# CONFIG_IP_ADVANCED_ROUTER is not set -CONFIG_IP_FIB_HASH=y -CONFIG_IP_PNP=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_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_INET_XFRM_MODE_BEET=y -# CONFIG_INET_LRO is not set -CONFIG_INET_DIAG=y -CONFIG_INET_TCP_DIAG=y -# CONFIG_TCP_CONG_ADVANCED is not set -CONFIG_TCP_CONG_CUBIC=y -CONFIG_DEFAULT_TCP_CONG="cubic" -# CONFIG_TCP_MD5SIG is not set -# CONFIG_IPV6 is not set -# CONFIG_INET6_XFRM_TUNNEL is not set -# CONFIG_INET6_TUNNEL is not set -# CONFIG_NETWORK_SECMARK is not set -# CONFIG_NETFILTER is not set -# CONFIG_IP_DCCP is not set -# CONFIG_IP_SCTP is not set -# CONFIG_TIPC is not set -# CONFIG_ATM is not set -# CONFIG_BRIDGE is not set -# CONFIG_VLAN_8021Q is not set -# CONFIG_DECNET is not set -# CONFIG_LLC2 is not set -# CONFIG_IPX is not set -# CONFIG_ATALK is not set -# CONFIG_X25 is not set -# CONFIG_LAPB is not set -# CONFIG_ECONET is not set -# CONFIG_WAN_ROUTER is not set -# CONFIG_NET_SCHED is not set - -# -# Network testing -# -# CONFIG_NET_PKTGEN is not set -# CONFIG_HAMRADIO is not set -# CONFIG_IRDA is not set -# CONFIG_BT is not set -# CONFIG_AF_RXRPC is not set - -# -# Wireless -# -# CONFIG_CFG80211 is not set -# CONFIG_WIRELESS_EXT is not set -# CONFIG_MAC80211 is not set -# CONFIG_IEEE80211 is not set -# CONFIG_RFKILL is not set -# CONFIG_NET_9P is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -CONFIG_BLK_DEV=y -# CONFIG_BLK_DEV_COW_COMMON is not set -CONFIG_BLK_DEV_LOOP=y -# CONFIG_BLK_DEV_CRYPTOLOOP is not set -# CONFIG_BLK_DEV_NBD is not set -CONFIG_BLK_DEV_RAM=y -CONFIG_BLK_DEV_RAM_COUNT=16 -CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -# CONFIG_CDROM_PKTCDVD is not set -# CONFIG_ATA_OVER_ETH is not set -CONFIG_MISC_DEVICES=y -# CONFIG_EEPROM_93CX6 is not set -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_ISCSI_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_ISCSI_TCP is not set -# CONFIG_SCSI_DEBUG is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -CONFIG_NETDEVICES=y -# CONFIG_NETDEVICES_MULTIQUEUE is not set -# CONFIG_DUMMY is not set -# CONFIG_BONDING is not set -# CONFIG_MACVLAN is not set -# CONFIG_EQUALIZER is not set -# CONFIG_TUN is not set -# CONFIG_VETH is not set -# CONFIG_PHYLIB is not set -CONFIG_NET_ETHERNET=y -# CONFIG_MII is not set -# CONFIG_STNIC is not set -# CONFIG_SMC91X is not set -# CONFIG_SMC911X is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_B44 is not set -CONFIG_NETDEV_1000=y -CONFIG_NETDEV_10000=y - -# -# Wireless LAN -# -# CONFIG_WLAN_PRE80211 is not set -# CONFIG_WLAN_80211 is not set -# CONFIG_WAN is not set -# CONFIG_PPP is not set -# CONFIG_SLIP is not set -# CONFIG_SHAPER is not set -# CONFIG_NETCONSOLE is not set -# CONFIG_NETPOLL is not set -# CONFIG_NET_POLL_CONTROLLER is not set -# CONFIG_ISDN is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=2 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -CONFIG_LEGACY_PTYS=y -CONFIG_LEGACY_PTY_COUNT=256 -# CONFIG_IPMI_HANDLER is not set -CONFIG_HW_RANDOM=y -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -CONFIG_HWMON=y -# CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_F71805F is not set -# CONFIG_SENSORS_F71882FG is not set -# CONFIG_SENSORS_IT87 is not set -# CONFIG_SENSORS_PC87360 is not set -# CONFIG_SENSORS_PC87427 is not set -# CONFIG_SENSORS_SMSC47M1 is not set -# CONFIG_SENSORS_SMSC47B397 is not set -# CONFIG_SENSORS_VT1211 is not set -# CONFIG_SENSORS_W83627HF is not set -# CONFIG_SENSORS_W83627EHF is not set -# CONFIG_HWMON_DEBUG_CHIP is not set -CONFIG_WATCHDOG=y -# CONFIG_WATCHDOG_NOWAYOUT is not set - -# -# Watchdog Device Drivers -# -# CONFIG_SOFT_WATCHDOG is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set -# CONFIG_DVB_CORE is not set -CONFIG_DAB=y - -# -# Graphics support -# -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB_DDC is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_LOGO_SUPERH_MONO is not set -# CONFIG_LOGO_SUPERH_VGA16 is not set -CONFIG_LOGO_SUPERH_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set -CONFIG_HID_SUPPORT=y -CONFIG_HID=y -# CONFIG_HID_DEBUG is not set -# CONFIG_HIDRAW is not set -CONFIG_USB_SUPPORT=y -CONFIG_USB_ARCH_HAS_HCD=y -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_ARCH_HAS_EHCI is not set -# CONFIG_USB is not set - -# -# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' -# - -# -# USB Gadget Support -# -# CONFIG_USB_GADGET is not set -# CONFIG_MMC is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_RTC_CLASS is not set - -# -# Userspace I/O -# -# CONFIG_UIO is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -# CONFIG_OCFS2_FS is not set -CONFIG_MINIX_FS=y -CONFIG_ROMFS_FS=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS 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=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set -CONFIG_NETWORK_FILESYSTEMS=y -CONFIG_NFS_FS=y -CONFIG_NFS_V3=y -# CONFIG_NFS_V3_ACL 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_LOCKD_V4=y -CONFIG_NFS_COMMON=y -CONFIG_SUNRPC=y -# CONFIG_SUNRPC_BIND34 is not set -# 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=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_NLS is not set -# CONFIG_DLM is not set -CONFIG_INSTRUMENTATION=y -# CONFIG_PROFILING is not set -# CONFIG_MARKERS is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y -CONFIG_SCHEDSTATS=y -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -# CONFIG_EARLY_PRINTK is not set -CONFIG_SH64_PROC_TLB=y -CONFIG_SH64_PROC_ASIDS=y -CONFIG_SH64_SR_WATCH=y -# CONFIG_POOR_MANS_STRACE is not set -# CONFIG_SH_NO_BSS_INIT is not set - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff -puN arch/sh64/configs/sim_defconfig~git-sh /dev/null --- a/arch/sh64/configs/sim_defconfig +++ /dev/null @@ -1,558 +0,0 @@ -# -# Automatically generated make config: don't edit -# Linux kernel version: 2.6.24-rc1 -# Fri Nov 2 14:36:08 2007 -# -CONFIG_SUPERH=y -CONFIG_SUPERH64=y -CONFIG_MMU=y -CONFIG_QUICKLIST=y -CONFIG_RWSEM_GENERIC_SPINLOCK=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_HWEIGHT=y -CONFIG_GENERIC_CALIBRATE_DELAY=y -CONFIG_GENERIC_HARDIRQS=y -CONFIG_GENERIC_IRQ_PROBE=y -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_ARCH_NO_VIRT_TO_BUS=y -CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" - -# -# General setup -# -CONFIG_EXPERIMENTAL=y -CONFIG_BROKEN_ON_SMP=y -CONFIG_LOCK_KERNEL=y -CONFIG_INIT_ENV_ARG_LIMIT=32 -CONFIG_LOCALVERSION="" -CONFIG_LOCALVERSION_AUTO=y -CONFIG_SWAP=y -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_USER_NS is not set -# CONFIG_IKCONFIG is not set -CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_CGROUPS is not set -CONFIG_FAIR_GROUP_SCHED=y -CONFIG_FAIR_USER_SCHED=y -# CONFIG_FAIR_CGROUP_SCHED is not set -CONFIG_SYSFS_DEPRECATED=y -# CONFIG_RELAY is not set -# CONFIG_BLK_DEV_INITRD is not set -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set -CONFIG_SYSCTL=y -# CONFIG_EMBEDDED is not set -CONFIG_UID16=y -CONFIG_SYSCTL_SYSCALL=y -CONFIG_KALLSYMS=y -# CONFIG_KALLSYMS_ALL is not set -# CONFIG_KALLSYMS_EXTRA_PASS is not set -CONFIG_HOTPLUG=y -CONFIG_PRINTK=y -CONFIG_BUG=y -CONFIG_ELF_CORE=y -CONFIG_BASE_FULL=y -CONFIG_FUTEX=y -CONFIG_ANON_INODES=y -CONFIG_EPOLL=y -CONFIG_SIGNALFD=y -CONFIG_EVENTFD=y -CONFIG_SHMEM=y -CONFIG_VM_EVENT_COUNTERS=y -CONFIG_SLAB=y -# CONFIG_SLUB is not set -# CONFIG_SLOB is not set -CONFIG_RT_MUTEXES=y -# CONFIG_TINY_SHMEM is not set -CONFIG_BASE_SMALL=0 -# CONFIG_MODULES is not set -CONFIG_BLOCK=y -# CONFIG_LBD is not set -# CONFIG_BLK_DEV_IO_TRACE is not set -# CONFIG_LSF is not set -# CONFIG_BLK_DEV_BSG is not set - -# -# IO Schedulers -# -CONFIG_IOSCHED_NOOP=y -CONFIG_IOSCHED_AS=y -CONFIG_IOSCHED_DEADLINE=y -CONFIG_IOSCHED_CFQ=y -# CONFIG_DEFAULT_AS is not set -# CONFIG_DEFAULT_DEADLINE is not set -CONFIG_DEFAULT_CFQ=y -# CONFIG_DEFAULT_NOOP is not set -CONFIG_DEFAULT_IOSCHED="cfq" - -# -# System type -# -CONFIG_SH_SIMULATOR=y -# CONFIG_SH_CAYMAN is not set -# CONFIG_SH_HARP is not set -CONFIG_CPU_SH5=y -CONFIG_CPU_SUBTYPE_SH5_101=y -# CONFIG_CPU_SUBTYPE_SH5_103 is not set -CONFIG_LITTLE_ENDIAN=y -# CONFIG_BIG_ENDIAN is not set -CONFIG_SH_FPU=y -# CONFIG_SH64_FPU_DENORM_FLUSH is not set -CONFIG_SH64_PGTABLE_2_LEVEL=y -# CONFIG_SH64_PGTABLE_3_LEVEL is not set -CONFIG_HUGETLB_PAGE_SIZE_64K=y -# CONFIG_HUGETLB_PAGE_SIZE_1MB is not set -# CONFIG_HUGETLB_PAGE_SIZE_512MB is not set -CONFIG_SH64_USER_MISALIGNED_FIXUP=y - -# -# Memory options -# -CONFIG_CACHED_MEMORY_OFFSET=0x20000000 -CONFIG_MEMORY_START=0x80000000 -CONFIG_MEMORY_SIZE_IN_MB=128 - -# -# Cache options -# -# CONFIG_DCACHE_WRITE_BACK is not set -# CONFIG_DCACHE_WRITE_THROUGH is not set -CONFIG_DCACHE_DISABLED=y -# CONFIG_ICACHE_DISABLED is not set -CONFIG_PCIDEVICE_MEMORY_START=C0000000 -CONFIG_DEVICE_MEMORY_START=E0000000 -CONFIG_FLASH_MEMORY_START=0x00000000 -CONFIG_PCI_BLOCK_START=0x40000000 - -# -# CPU Subtype specific options -# -CONFIG_SH64_ID2815_WORKAROUND=y - -# -# Misc options -# -# CONFIG_SH_DMA is not set -CONFIG_PREEMPT=y -CONFIG_SELECT_MEMORY_MODEL=y -CONFIG_FLATMEM_MANUAL=y -# CONFIG_DISCONTIGMEM_MANUAL is not set -# CONFIG_SPARSEMEM_MANUAL is not set -CONFIG_FLATMEM=y -CONFIG_FLAT_NODE_MEM_MAP=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -CONFIG_SPLIT_PTLOCK_CPUS=4 -# CONFIG_RESOURCES_64BIT is not set -CONFIG_ZONE_DMA_FLAG=0 -CONFIG_NR_QUICK=1 - -# -# Bus options (PCI, PCMCIA, EISA, MCA, ISA) -# -# CONFIG_ARCH_SUPPORTS_MSI is not set -# CONFIG_PCCARD is not set - -# -# Executable file formats -# -CONFIG_BINFMT_ELF=y -# CONFIG_BINFMT_MISC is not set - -# -# Networking -# -# CONFIG_NET is not set - -# -# Device Drivers -# - -# -# Generic Driver Options -# -CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -CONFIG_STANDALONE=y -CONFIG_PREVENT_FIRMWARE_BUILD=y -# CONFIG_FW_LOADER is not set -# CONFIG_DEBUG_DRIVER is not set -# CONFIG_DEBUG_DEVRES is not set -# CONFIG_SYS_HYPERVISOR is not set -# CONFIG_MTD is not set -# CONFIG_PARPORT is not set -# CONFIG_BLK_DEV is not set -# CONFIG_MISC_DEVICES is not set -# CONFIG_IDE is not set - -# -# SCSI device support -# -# CONFIG_RAID_ATTRS is not set -CONFIG_SCSI=y -CONFIG_SCSI_DMA=y -# CONFIG_SCSI_TGT is not set -# CONFIG_SCSI_NETLINK is not set -CONFIG_SCSI_PROC_FS=y - -# -# SCSI support type (disk, tape, CD-ROM) -# -CONFIG_BLK_DEV_SD=y -# CONFIG_CHR_DEV_ST is not set -# CONFIG_CHR_DEV_OSST is not set -# CONFIG_BLK_DEV_SR is not set -# CONFIG_CHR_DEV_SG is not set -# CONFIG_CHR_DEV_SCH is not set - -# -# Some SCSI devices (e.g. CD jukebox) support multiple LUNs -# -CONFIG_SCSI_MULTI_LUN=y -# CONFIG_SCSI_CONSTANTS is not set -# CONFIG_SCSI_LOGGING is not set -# CONFIG_SCSI_SCAN_ASYNC is not set - -# -# SCSI Transports -# -CONFIG_SCSI_SPI_ATTRS=y -# CONFIG_SCSI_FC_ATTRS is not set -# CONFIG_SCSI_SAS_LIBSAS is not set -# CONFIG_SCSI_SRP_ATTRS is not set -CONFIG_SCSI_LOWLEVEL=y -# CONFIG_SCSI_DEBUG is not set -# CONFIG_ATA is not set -# CONFIG_MD is not set -# CONFIG_PHONE is not set - -# -# Input device support -# -CONFIG_INPUT=y -# CONFIG_INPUT_FF_MEMLESS is not set -# CONFIG_INPUT_POLLDEV is not set - -# -# Userland interfaces -# -CONFIG_INPUT_MOUSEDEV=y -# CONFIG_INPUT_MOUSEDEV_PSAUX is not set -CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 -CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 -# CONFIG_INPUT_JOYDEV is not set -# CONFIG_INPUT_EVDEV is not set -# CONFIG_INPUT_EVBUG is not set - -# -# Input Device Drivers -# -# CONFIG_INPUT_KEYBOARD is not set -# CONFIG_INPUT_MOUSE is not set -# CONFIG_INPUT_JOYSTICK is not set -# CONFIG_INPUT_TABLET is not set -# CONFIG_INPUT_TOUCHSCREEN is not set -# CONFIG_INPUT_MISC is not set - -# -# Hardware I/O ports -# -# CONFIG_SERIO is not set -# CONFIG_GAMEPORT is not set - -# -# Character devices -# -CONFIG_VT=y -CONFIG_VT_CONSOLE=y -CONFIG_HW_CONSOLE=y -# CONFIG_VT_HW_CONSOLE_BINDING is not set -# CONFIG_SERIAL_NONSTANDARD is not set - -# -# Serial drivers -# -# CONFIG_SERIAL_8250 is not set - -# -# Non-8250 serial port support -# -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_NR_UARTS=2 -CONFIG_SERIAL_SH_SCI_CONSOLE=y -CONFIG_SERIAL_CORE=y -CONFIG_SERIAL_CORE_CONSOLE=y -CONFIG_UNIX98_PTYS=y -# CONFIG_LEGACY_PTYS is not set -# CONFIG_IPMI_HANDLER is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_R3964 is not set -# CONFIG_RAW_DRIVER is not set -# CONFIG_TCG_TPM is not set -# CONFIG_I2C is not set - -# -# SPI support -# -# CONFIG_SPI is not set -# CONFIG_SPI_MASTER is not set -# CONFIG_W1 is not set -# CONFIG_POWER_SUPPLY is not set -# CONFIG_HWMON is not set -# CONFIG_WATCHDOG is not set - -# -# Sonics Silicon Backplane -# -CONFIG_SSB_POSSIBLE=y -# CONFIG_SSB is not set - -# -# Multifunction device drivers -# -# CONFIG_MFD_SM501 is not set - -# -# Multimedia devices -# -# CONFIG_VIDEO_DEV is not set -CONFIG_DAB=y - -# -# Graphics support -# -# CONFIG_VGASTATE is not set -CONFIG_VIDEO_OUTPUT_CONTROL=y -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB_DDC is not set -# CONFIG_FB_CFB_FILLRECT is not set -# CONFIG_FB_CFB_COPYAREA is not set -# CONFIG_FB_CFB_IMAGEBLIT is not set -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_SYS_FOPS is not set -CONFIG_FB_DEFERRED_IO=y -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -# CONFIG_FB_TILEBLITTING is not set - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set - -# -# Display device support -# -# CONFIG_DISPLAY_SUPPORT is not set - -# -# Console display driver support -# -CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -CONFIG_FONTS=y -# CONFIG_FONT_8x8 is not set -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -CONFIG_LOGO=y -# CONFIG_LOGO_LINUX_MONO is not set -# CONFIG_LOGO_LINUX_VGA16 is not set -# CONFIG_LOGO_LINUX_CLUT224 is not set -# CONFIG_LOGO_SUPERH_MONO is not set -# CONFIG_LOGO_SUPERH_VGA16 is not set -CONFIG_LOGO_SUPERH_CLUT224=y - -# -# Sound -# -# CONFIG_SOUND is not set -# CONFIG_HID_SUPPORT is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_MMC is not set -# CONFIG_NEW_LEDS is not set -# CONFIG_RTC_CLASS is not set - -# -# Userspace I/O -# -# CONFIG_UIO is not set - -# -# File systems -# -CONFIG_EXT2_FS=y -# CONFIG_EXT2_FS_XATTR is not set -# CONFIG_EXT2_FS_XIP is not set -CONFIG_EXT3_FS=y -CONFIG_EXT3_FS_XATTR=y -# CONFIG_EXT3_FS_POSIX_ACL is not set -# CONFIG_EXT3_FS_SECURITY is not set -# CONFIG_EXT4DEV_FS is not set -CONFIG_JBD=y -# CONFIG_JBD_DEBUG is not set -CONFIG_FS_MBCACHE=y -# CONFIG_REISERFS_FS is not set -# CONFIG_JFS_FS is not set -# CONFIG_FS_POSIX_ACL is not set -# CONFIG_XFS_FS is not set -# CONFIG_GFS2_FS is not set -CONFIG_MINIX_FS=y -CONFIG_ROMFS_FS=y -CONFIG_INOTIFY=y -CONFIG_INOTIFY_USER=y -# CONFIG_QUOTA is not set -CONFIG_DNOTIFY=y -# CONFIG_AUTOFS_FS is not set -# CONFIG_AUTOFS4_FS 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=y -CONFIG_PROC_SYSCTL=y -CONFIG_SYSFS=y -CONFIG_TMPFS=y -# CONFIG_TMPFS_POSIX_ACL is not set -CONFIG_HUGETLBFS=y -CONFIG_HUGETLB_PAGE=y -# CONFIG_CONFIGFS_FS is not set - -# -# Miscellaneous filesystems -# -# CONFIG_ADFS_FS is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_HFSPLUS_FS is not set -# CONFIG_BEFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_VXFS_FS is not set -# CONFIG_HPFS_FS is not set -# CONFIG_QNX4FS_FS is not set -# CONFIG_SYSV_FS is not set -# CONFIG_UFS_FS is not set - -# -# Partition Types -# -CONFIG_PARTITION_ADVANCED=y -# CONFIG_ACORN_PARTITION is not set -# CONFIG_OSF_PARTITION is not set -# CONFIG_AMIGA_PARTITION is not set -# CONFIG_ATARI_PARTITION is not set -# CONFIG_MAC_PARTITION is not set -CONFIG_MSDOS_PARTITION=y -# CONFIG_BSD_DISKLABEL is not set -# CONFIG_MINIX_SUBPARTITION is not set -# CONFIG_SOLARIS_X86_PARTITION is not set -# CONFIG_UNIXWARE_DISKLABEL is not set -# CONFIG_LDM_PARTITION is not set -# CONFIG_SGI_PARTITION is not set -# CONFIG_ULTRIX_PARTITION is not set -# CONFIG_SUN_PARTITION is not set -# CONFIG_KARMA_PARTITION is not set -# CONFIG_EFI_PARTITION is not set -# CONFIG_SYSV68_PARTITION is not set -# CONFIG_NLS is not set -CONFIG_INSTRUMENTATION=y -CONFIG_PROFILING=y -# CONFIG_OPROFILE is not set -# CONFIG_MARKERS is not set - -# -# Kernel hacking -# -# CONFIG_PRINTK_TIME is not set -CONFIG_ENABLE_WARN_DEPRECATED=y -CONFIG_ENABLE_MUST_CHECK=y -CONFIG_MAGIC_SYSRQ=y -# CONFIG_UNUSED_SYMBOLS is not set -CONFIG_DEBUG_FS=y -# CONFIG_HEADERS_CHECK is not set -CONFIG_DEBUG_KERNEL=y -# CONFIG_DEBUG_SHIRQ is not set -CONFIG_DETECT_SOFTLOCKUP=y -CONFIG_SCHED_DEBUG=y -CONFIG_SCHEDSTATS=y -# CONFIG_TIMER_STATS is not set -# CONFIG_DEBUG_SLAB is not set -# CONFIG_DEBUG_RT_MUTEXES is not set -# CONFIG_RT_MUTEX_TESTER is not set -# CONFIG_DEBUG_SPINLOCK is not set -# CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_SPINLOCK_SLEEP is not set -# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set -# CONFIG_DEBUG_KOBJECT is not set -CONFIG_DEBUG_BUGVERBOSE=y -# CONFIG_DEBUG_INFO is not set -# CONFIG_DEBUG_VM is not set -# CONFIG_DEBUG_LIST is not set -# CONFIG_DEBUG_SG is not set -CONFIG_FRAME_POINTER=y -CONFIG_FORCED_INLINING=y -# CONFIG_BOOT_PRINTK_DELAY is not set -# CONFIG_FAULT_INJECTION is not set -# CONFIG_SAMPLES is not set -# CONFIG_EARLY_PRINTK is not set -CONFIG_SH64_PROC_TLB=y -CONFIG_SH64_PROC_ASIDS=y -CONFIG_SH64_SR_WATCH=y -# CONFIG_POOR_MANS_STRACE is not set -CONFIG_SH_NO_BSS_INIT=y - -# -# Security options -# -# CONFIG_KEYS is not set -# CONFIG_SECURITY is not set -# CONFIG_SECURITY_FILE_CAPABILITIES is not set -# CONFIG_CRYPTO is not set - -# -# Library routines -# -CONFIG_BITREVERSE=y -# CONFIG_CRC_CCITT is not set -# CONFIG_CRC16 is not set -# CONFIG_CRC_ITU_T is not set -CONFIG_CRC32=y -# CONFIG_CRC7 is not set -# CONFIG_LIBCRC32C is not set -CONFIG_PLIST=y -CONFIG_HAS_IOMEM=y -CONFIG_HAS_IOPORT=y -CONFIG_HAS_DMA=y diff -puN arch/sh64/kernel/Makefile~git-sh /dev/null --- a/arch/sh64/kernel/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2000, 2001 Paolo Alberelli -# Copyright (C) 2003 Paul Mundt -# -# Makefile for the Linux sh64 kernel. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -extra-y := head.o init_task.o vmlinux.lds - -obj-y := process.o signal.o entry.o traps.o irq.o irq_intc.o \ - ptrace.o setup.o time.o sys_sh64.o semaphore.o sh_ksyms.o \ - switchto.o syscalls.o - -obj-$(CONFIG_HEARTBEAT) += led.o -obj-$(CONFIG_SH_ALPHANUMERIC) += alphanum.o -obj-$(CONFIG_SH_DMA) += dma.o -obj-$(CONFIG_SH_FPU) += fpu.o -obj-$(CONFIG_EARLY_PRINTK) += early_printk.o -obj-$(CONFIG_KALLSYMS) += unwind.o -obj-$(CONFIG_PCI) += pcibios.o -obj-$(CONFIG_MODULES) += module.o - -ifeq ($(CONFIG_PCI),y) -obj-$(CONFIG_CPU_SH5) += pci_sh5.o -endif - -USE_STANDARD_AS_RULE := true - diff -puN arch/sh64/kernel/alphanum.c~git-sh /dev/null --- a/arch/sh64/kernel/alphanum.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * arch/sh64/kernel/alphanum.c - * - * Copyright (C) 2002 Stuart Menefy - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Machine-independent functions for handling 8-digit alphanumeric display - * (e.g. Agilent HDSP-253x) - */ -#include -#include - -void mach_alphanum(int pos, unsigned char val); - -void print_seg(char *file, int line) -{ - int i; - unsigned int nibble; - - for (i = 0; i < 5; i++) { - mach_alphanum(i, file[i]); - } - - for (i = 0; i < 3; i++) { - nibble = ((line >> (i * 4)) & 0xf); - mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48)); - } -} - -void print_seg_num(unsigned num) -{ - int i; - unsigned int nibble; - - for (i = 0; i < 8; i++) { - nibble = ((num >> (i * 4)) & 0xf); - - mach_alphanum(7 - i, nibble + ((nibble > 9) ? 55 : 48)); - } -} - diff -puN arch/sh64/kernel/asm-offsets.c~git-sh /dev/null --- a/arch/sh64/kernel/asm-offsets.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include -#include -#include -#include - -#define DEFINE(sym, val) \ - asm volatile("\n->" #sym " %0 " #val : : "i" (val)) - -#define BLANK() asm volatile("\n->" : : ) - -int main(void) -{ - /* offsets into the thread_info struct */ - DEFINE(TI_TASK, offsetof(struct thread_info, task)); - DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); - DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); - DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); - DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_RESTART_BLOCK,offsetof(struct thread_info, restart_block)); - - return 0; -} diff -puN arch/sh64/kernel/dma.c~git-sh /dev/null --- a/arch/sh64/kernel/dma.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * arch/sh64/kernel/dma.c - * - * DMA routines for the SH-5 DMAC. - * - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - unsigned long dev_addr; - unsigned long mem_addr; - - unsigned int mode; - unsigned int count; -} dma_info_t; - -static dma_info_t dma_info[MAX_DMA_CHANNELS]; -static DEFINE_SPINLOCK(dma_spin_lock); - -/* arch/sh64/kernel/irq_intc.c */ -extern void make_intc_irq(unsigned int irq); - -/* DMAC Interrupts */ -#define DMA_IRQ_DMTE0 18 -#define DMA_IRQ_DERR 22 - -#define DMAC_COMMON_BASE (dmac_base + 0x08) -#define DMAC_SAR_BASE (dmac_base + 0x10) -#define DMAC_DAR_BASE (dmac_base + 0x18) -#define DMAC_COUNT_BASE (dmac_base + 0x20) -#define DMAC_CTRL_BASE (dmac_base + 0x28) -#define DMAC_STATUS_BASE (dmac_base + 0x30) - -#define DMAC_SAR(n) (DMAC_SAR_BASE + ((n) * 0x28)) -#define DMAC_DAR(n) (DMAC_DAR_BASE + ((n) * 0x28)) -#define DMAC_COUNT(n) (DMAC_COUNT_BASE + ((n) * 0x28)) -#define DMAC_CTRL(n) (DMAC_CTRL_BASE + ((n) * 0x28)) -#define DMAC_STATUS(n) (DMAC_STATUS_BASE + ((n) * 0x28)) - -/* DMAC.COMMON Bit Definitions */ -#define DMAC_COMMON_PR 0x00000001 /* Priority */ - /* Bits 1-2 Reserved */ -#define DMAC_COMMON_ME 0x00000008 /* Master Enable */ -#define DMAC_COMMON_NMI 0x00000010 /* NMI Flag */ - /* Bits 5-6 Reserved */ -#define DMAC_COMMON_ER 0x00000780 /* Error Response */ -#define DMAC_COMMON_AAE 0x00007800 /* Address Alignment Error */ - /* Bits 15-63 Reserved */ - -/* DMAC.SAR Bit Definitions */ -#define DMAC_SAR_ADDR 0xffffffff /* Source Address */ - -/* DMAC.DAR Bit Definitions */ -#define DMAC_DAR_ADDR 0xffffffff /* Destination Address */ - -/* DMAC.COUNT Bit Definitions */ -#define DMAC_COUNT_CNT 0xffffffff /* Transfer Count */ - -/* DMAC.CTRL Bit Definitions */ -#define DMAC_CTRL_TS 0x00000007 /* Transfer Size */ -#define DMAC_CTRL_SI 0x00000018 /* Source Increment */ -#define DMAC_CTRL_DI 0x00000060 /* Destination Increment */ -#define DMAC_CTRL_RS 0x00000780 /* Resource Select */ -#define DMAC_CTRL_IE 0x00000800 /* Interrupt Enable */ -#define DMAC_CTRL_TE 0x00001000 /* Transfer Enable */ - /* Bits 15-63 Reserved */ - -/* DMAC.STATUS Bit Definitions */ -#define DMAC_STATUS_TE 0x00000001 /* Transfer End */ -#define DMAC_STATUS_AAE 0x00000002 /* Address Alignment Error */ - /* Bits 2-63 Reserved */ - -static unsigned long dmac_base; - -void set_dma_count(unsigned int chan, unsigned int count); -void set_dma_addr(unsigned int chan, unsigned int addr); - -static irqreturn_t dma_mte(int irq, void *dev_id, struct pt_regs *regs) -{ - unsigned int chan = irq - DMA_IRQ_DMTE0; - dma_info_t *info = dma_info + chan; - u64 status; - - if (info->mode & DMA_MODE_WRITE) { - sh64_out64(info->mem_addr & DMAC_SAR_ADDR, DMAC_SAR(chan)); - } else { - sh64_out64(info->mem_addr & DMAC_DAR_ADDR, DMAC_DAR(chan)); - } - - set_dma_count(chan, info->count); - - /* Clear the TE bit */ - status = sh64_in64(DMAC_STATUS(chan)); - status &= ~DMAC_STATUS_TE; - sh64_out64(status, DMAC_STATUS(chan)); - - return IRQ_HANDLED; -} - -static struct irqaction irq_dmte = { - .handler = dma_mte, - .flags = IRQF_DISABLED, - .name = "DMA MTE", -}; - -static irqreturn_t dma_err(int irq, void *dev_id, struct pt_regs *regs) -{ - u64 tmp; - u8 chan; - - printk(KERN_NOTICE "DMAC: Got a DMA Error!\n"); - - tmp = sh64_in64(DMAC_COMMON_BASE); - - /* Check for the type of error */ - if ((chan = tmp & DMAC_COMMON_AAE)) { - /* It's an address alignment error.. */ - printk(KERN_NOTICE "DMAC: Alignment error on channel %d, ", chan); - - printk(KERN_NOTICE "SAR: 0x%08llx, DAR: 0x%08llx, COUNT: %lld\n", - (sh64_in64(DMAC_SAR(chan)) & DMAC_SAR_ADDR), - (sh64_in64(DMAC_DAR(chan)) & DMAC_DAR_ADDR), - (sh64_in64(DMAC_COUNT(chan)) & DMAC_COUNT_CNT)); - - } else if ((chan = tmp & DMAC_COMMON_ER)) { - /* Something else went wrong.. */ - printk(KERN_NOTICE "DMAC: Error on channel %d\n", chan); - } - - /* Reset the ME bit to clear the interrupt */ - tmp |= DMAC_COMMON_ME; - sh64_out64(tmp, DMAC_COMMON_BASE); - - return IRQ_HANDLED; -} - -static struct irqaction irq_derr = { - .handler = dma_err, - .flags = IRQF_DISABLED, - .name = "DMA Error", -}; - -static inline unsigned long calc_xmit_shift(unsigned int chan) -{ - return sh64_in64(DMAC_CTRL(chan)) & 0x03; -} - -void setup_dma(unsigned int chan, dma_info_t *info) -{ - unsigned int irq = DMA_IRQ_DMTE0 + chan; - dma_info_t *dma = dma_info + chan; - - make_intc_irq(irq); - setup_irq(irq, &irq_dmte); - dma = info; -} - -void enable_dma(unsigned int chan) -{ - u64 ctrl; - - ctrl = sh64_in64(DMAC_CTRL(chan)); - ctrl |= DMAC_CTRL_TE; - sh64_out64(ctrl, DMAC_CTRL(chan)); -} - -void disable_dma(unsigned int chan) -{ - u64 ctrl; - - ctrl = sh64_in64(DMAC_CTRL(chan)); - ctrl &= ~DMAC_CTRL_TE; - sh64_out64(ctrl, DMAC_CTRL(chan)); -} - -void set_dma_mode(unsigned int chan, char mode) -{ - dma_info_t *info = dma_info + chan; - - info->mode = mode; - - set_dma_addr(chan, info->mem_addr); - set_dma_count(chan, info->count); -} - -void set_dma_addr(unsigned int chan, unsigned int addr) -{ - dma_info_t *info = dma_info + chan; - unsigned long sar, dar; - - info->mem_addr = addr; - sar = (info->mode & DMA_MODE_WRITE) ? info->mem_addr : info->dev_addr; - dar = (info->mode & DMA_MODE_WRITE) ? info->dev_addr : info->mem_addr; - - sh64_out64(sar & DMAC_SAR_ADDR, DMAC_SAR(chan)); - sh64_out64(dar & DMAC_SAR_ADDR, DMAC_DAR(chan)); -} - -void set_dma_count(unsigned int chan, unsigned int count) -{ - dma_info_t *info = dma_info + chan; - u64 tmp; - - info->count = count; - - tmp = (info->count >> calc_xmit_shift(chan)) & DMAC_COUNT_CNT; - - sh64_out64(tmp, DMAC_COUNT(chan)); -} - -unsigned long claim_dma_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&dma_spin_lock, flags); - - return flags; -} - -void release_dma_lock(unsigned long flags) -{ - spin_unlock_irqrestore(&dma_spin_lock, flags); -} - -int get_dma_residue(unsigned int chan) -{ - return sh64_in64(DMAC_COUNT(chan) << calc_xmit_shift(chan)); -} - -int __init init_dma(void) -{ - struct vcr_info vcr; - u64 tmp; - - /* Remap the DMAC */ - dmac_base = onchip_remap(PHYS_DMAC_BLOCK, 1024, "DMAC"); - if (!dmac_base) { - printk(KERN_ERR "Unable to remap DMAC\n"); - return -ENOMEM; - } - - /* Report DMAC.VCR Info */ - vcr = sh64_get_vcr_info(dmac_base); - printk("DMAC: Module ID: 0x%04x, Module version: 0x%04x\n", - vcr.mod_id, vcr.mod_vers); - - /* Set the ME bit */ - tmp = sh64_in64(DMAC_COMMON_BASE); - tmp |= DMAC_COMMON_ME; - sh64_out64(tmp, DMAC_COMMON_BASE); - - /* Enable the DMAC Error Interrupt */ - make_intc_irq(DMA_IRQ_DERR); - setup_irq(DMA_IRQ_DERR, &irq_derr); - - return 0; -} - -static void __exit exit_dma(void) -{ - onchip_unmap(dmac_base); - free_irq(DMA_IRQ_DERR, 0); -} - -module_init(init_dma); -module_exit(exit_dma); - -MODULE_AUTHOR("Paul Mundt"); -MODULE_DESCRIPTION("DMA API for SH-5 DMAC"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(setup_dma); -EXPORT_SYMBOL(claim_dma_lock); -EXPORT_SYMBOL(release_dma_lock); -EXPORT_SYMBOL(enable_dma); -EXPORT_SYMBOL(disable_dma); -EXPORT_SYMBOL(set_dma_mode); -EXPORT_SYMBOL(set_dma_addr); -EXPORT_SYMBOL(set_dma_count); -EXPORT_SYMBOL(get_dma_residue); - diff -puN arch/sh64/kernel/early_printk.c~git-sh /dev/null --- a/arch/sh64/kernel/early_printk.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * arch/sh64/kernel/early_printk.c - * - * SH-5 Early SCIF console (cloned and hacked from sh implementation) - * - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2002 M. R. Brown - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include - -#define SCIF_BASE_ADDR 0x01030000 -#define SCIF_ADDR_SH5 PHYS_PERIPHERAL_BLOCK+SCIF_BASE_ADDR - -/* - * Fixed virtual address where SCIF is mapped (should already be done - * in arch/sh64/kernel/head.S!). - */ -#define SCIF_REG 0xfa030000 - -enum { - SCIF_SCSMR2 = SCIF_REG + 0x00, - SCIF_SCBRR2 = SCIF_REG + 0x04, - SCIF_SCSCR2 = SCIF_REG + 0x08, - SCIF_SCFTDR2 = SCIF_REG + 0x0c, - SCIF_SCFSR2 = SCIF_REG + 0x10, - SCIF_SCFRDR2 = SCIF_REG + 0x14, - SCIF_SCFCR2 = SCIF_REG + 0x18, - SCIF_SCFDR2 = SCIF_REG + 0x1c, - SCIF_SCSPTR2 = SCIF_REG + 0x20, - SCIF_SCLSR2 = SCIF_REG + 0x24, -}; - -static void sh_console_putc(int c) -{ - while (!(ctrl_inw(SCIF_SCFSR2) & 0x20)) - cpu_relax(); - - ctrl_outb(c, SCIF_SCFTDR2); - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0x9f), SCIF_SCFSR2); - - if (c == '\n') - sh_console_putc('\r'); -} - -static void sh_console_flush(void) -{ - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2); - - while (!(ctrl_inw(SCIF_SCFSR2) & 0x40)) - cpu_relax(); - - ctrl_outw((ctrl_inw(SCIF_SCFSR2) & 0xbf), SCIF_SCFSR2); -} - -static void sh_console_write(struct console *con, const char *s, unsigned count) -{ - while (count-- > 0) - sh_console_putc(*s++); - - sh_console_flush(); -} - -static int __init sh_console_setup(struct console *con, char *options) -{ - con->cflag = CREAD | HUPCL | CLOCAL | B19200 | CS8; - - return 0; -} - -static struct console sh_console = { - .name = "scifcon", - .write = sh_console_write, - .setup = sh_console_setup, - .flags = CON_PRINTBUFFER | CON_BOOT, - .index = -1, -}; - -void __init enable_early_printk(void) -{ - ctrl_outb(0x2a, SCIF_SCBRR2); /* 19200bps */ - - ctrl_outw(0x04, SCIF_SCFCR2); /* Reset TFRST */ - ctrl_outw(0x10, SCIF_SCFCR2); /* TTRG0=1 */ - - ctrl_outw(0, SCIF_SCSPTR2); - ctrl_outw(0x60, SCIF_SCFSR2); - ctrl_outw(0, SCIF_SCLSR2); - ctrl_outw(0x30, SCIF_SCSCR2); - - register_console(&sh_console); -} diff -puN arch/sh64/kernel/entry.S~git-sh /dev/null --- a/arch/sh64/kernel/entry.S +++ /dev/null @@ -1,2102 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/entry.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004, 2005 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - */ - -#include -#include - -#include -#include -#include -#include -#include - -/* - * SR fields. - */ -#define SR_ASID_MASK 0x00ff0000 -#define SR_FD_MASK 0x00008000 -#define SR_SS 0x08000000 -#define SR_BL 0x10000000 -#define SR_MD 0x40000000 - -/* - * Event code. - */ -#define EVENT_INTERRUPT 0 -#define EVENT_FAULT_TLB 1 -#define EVENT_FAULT_NOT_TLB 2 -#define EVENT_DEBUG 3 - -/* EXPEVT values */ -#define RESET_CAUSE 0x20 -#define DEBUGSS_CAUSE 0x980 - -/* - * Frame layout. Quad index. - */ -#define FRAME_T(x) FRAME_TBASE+(x*8) -#define FRAME_R(x) FRAME_RBASE+(x*8) -#define FRAME_S(x) FRAME_SBASE+(x*8) -#define FSPC 0 -#define FSSR 1 -#define FSYSCALL_ID 2 - -/* Arrange the save frame to be a multiple of 32 bytes long */ -#define FRAME_SBASE 0 -#define FRAME_RBASE (FRAME_SBASE+(3*8)) /* SYSCALL_ID - SSR - SPC */ -#define FRAME_TBASE (FRAME_RBASE+(63*8)) /* r0 - r62 */ -#define FRAME_PBASE (FRAME_TBASE+(8*8)) /* tr0 -tr7 */ -#define FRAME_SIZE (FRAME_PBASE+(2*8)) /* pad0-pad1 */ - -#define FP_FRAME_SIZE FP_FRAME_BASE+(33*8) /* dr0 - dr31 + fpscr */ -#define FP_FRAME_BASE 0 - -#define SAVED_R2 0*8 -#define SAVED_R3 1*8 -#define SAVED_R4 2*8 -#define SAVED_R5 3*8 -#define SAVED_R18 4*8 -#define SAVED_R6 5*8 -#define SAVED_TR0 6*8 - -/* These are the registers saved in the TLB path that aren't saved in the first - level of the normal one. */ -#define TLB_SAVED_R25 7*8 -#define TLB_SAVED_TR1 8*8 -#define TLB_SAVED_TR2 9*8 -#define TLB_SAVED_TR3 10*8 -#define TLB_SAVED_TR4 11*8 -/* Save R0/R1 : PT-migrating compiler currently dishounours -ffixed-r0 and -ffixed-r1 causing - breakage otherwise. */ -#define TLB_SAVED_R0 12*8 -#define TLB_SAVED_R1 13*8 - -#define CLI() \ - getcon SR, r6; \ - ori r6, 0xf0, r6; \ - putcon r6, SR; - -#define STI() \ - getcon SR, r6; \ - andi r6, ~0xf0, r6; \ - putcon r6, SR; - -#ifdef CONFIG_PREEMPT -# define preempt_stop() CLI() -#else -# define preempt_stop() -# define resume_kernel restore_all -#endif - - .section .data, "aw" - -#define FAST_TLBMISS_STACK_CACHELINES 4 -#define FAST_TLBMISS_STACK_QUADWORDS (4*FAST_TLBMISS_STACK_CACHELINES) - -/* Register back-up area for all exceptions */ - .balign 32 - /* Allow for 16 quadwords to be pushed by fast tlbmiss handling - * register saves etc. */ - .fill FAST_TLBMISS_STACK_QUADWORDS, 8, 0x0 -/* This is 32 byte aligned by construction */ -/* Register back-up area for all exceptions */ -reg_save_area: - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - .quad 0 - .quad 0 - - .quad 0 - .quad 0 - -/* Save area for RESVEC exceptions. We cannot use reg_save_area because of - * reentrancy. Note this area may be accessed via physical address. - * Align so this fits a whole single cache line, for ease of purging. - */ - .balign 32,0,32 -resvec_save_area: - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .quad 0 - .balign 32,0,32 - -/* Jump table of 3rd level handlers */ -trap_jtable: - .long do_exception_error /* 0x000 */ - .long do_exception_error /* 0x020 */ - .long tlb_miss_load /* 0x040 */ - .long tlb_miss_store /* 0x060 */ - ! ARTIFICIAL pseudo-EXPEVT setting - .long do_debug_interrupt /* 0x080 */ - .long tlb_miss_load /* 0x0A0 */ - .long tlb_miss_store /* 0x0C0 */ - .long do_address_error_load /* 0x0E0 */ - .long do_address_error_store /* 0x100 */ -#ifdef CONFIG_SH_FPU - .long do_fpu_error /* 0x120 */ -#else - .long do_exception_error /* 0x120 */ -#endif - .long do_exception_error /* 0x140 */ - .long system_call /* 0x160 */ - .long do_reserved_inst /* 0x180 */ - .long do_illegal_slot_inst /* 0x1A0 */ - .long do_NMI /* 0x1C0 */ - .long do_exception_error /* 0x1E0 */ - .rept 15 - .long do_IRQ /* 0x200 - 0x3C0 */ - .endr - .long do_exception_error /* 0x3E0 */ - .rept 32 - .long do_IRQ /* 0x400 - 0x7E0 */ - .endr - .long fpu_error_or_IRQA /* 0x800 */ - .long fpu_error_or_IRQB /* 0x820 */ - .long do_IRQ /* 0x840 */ - .long do_IRQ /* 0x860 */ - .rept 6 - .long do_exception_error /* 0x880 - 0x920 */ - .endr - .long do_software_break_point /* 0x940 */ - .long do_exception_error /* 0x960 */ - .long do_single_step /* 0x980 */ - - .rept 3 - .long do_exception_error /* 0x9A0 - 0x9E0 */ - .endr - .long do_IRQ /* 0xA00 */ - .long do_IRQ /* 0xA20 */ - .long itlb_miss_or_IRQ /* 0xA40 */ - .long do_IRQ /* 0xA60 */ - .long do_IRQ /* 0xA80 */ - .long itlb_miss_or_IRQ /* 0xAA0 */ - .long do_exception_error /* 0xAC0 */ - .long do_address_error_exec /* 0xAE0 */ - .rept 8 - .long do_exception_error /* 0xB00 - 0xBE0 */ - .endr - .rept 18 - .long do_IRQ /* 0xC00 - 0xE20 */ - .endr - - .section .text64, "ax" - -/* - * --- Exception/Interrupt/Event Handling Section - */ - -/* - * VBR and RESVEC blocks. - * - * First level handler for VBR-based exceptions. - * - * To avoid waste of space, align to the maximum text block size. - * This is assumed to be at most 128 bytes or 32 instructions. - * DO NOT EXCEED 32 instructions on the first level handlers ! - * - * Also note that RESVEC is contained within the VBR block - * where the room left (1KB - TEXT_SIZE) allows placing - * the RESVEC block (at most 512B + TEXT_SIZE). - * - * So first (and only) level handler for RESVEC-based exceptions. - * - * Where the fault/interrupt is handled (not_a_tlb_miss, tlb_miss - * and interrupt) we are a lot tight with register space until - * saving onto the stack frame, which is done in handle_exception(). - * - */ - -#define TEXT_SIZE 128 -#define BLOCK_SIZE 1664 /* Dynamic check, 13*128 */ - - .balign TEXT_SIZE -LVBR_block: - .space 256, 0 /* Power-on class handler, */ - /* not required here */ -not_a_tlb_miss: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* Save original stack pointer into KCR1 */ - putcon SP, KCR1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for Non-debug, Not a TLB miss class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_NOT_TLB, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - - .balign 256 - ! VBR+0x200 - nop - .balign 256 - ! VBR+0x300 - nop - .balign 256 - /* - * Instead of the natural .balign 1024 place RESVEC here - * respecting the final 1KB alignment. - */ - .balign TEXT_SIZE - /* - * Instead of '.space 1024-TEXT_SIZE' place the RESVEC - * block making sure the final alignment is correct. - */ -tlb_miss: - synco /* TAKum03020 (but probably a good idea anyway.) */ - putcon SP, KCR1 - movi reg_save_area, SP - /* SP is guaranteed 32-byte aligned. */ - st.q SP, TLB_SAVED_R0 , r0 - st.q SP, TLB_SAVED_R1 , r1 - st.q SP, SAVED_R2 , r2 - st.q SP, SAVED_R3 , r3 - st.q SP, SAVED_R4 , r4 - st.q SP, SAVED_R5 , r5 - st.q SP, SAVED_R6 , r6 - st.q SP, SAVED_R18, r18 - - /* Save R25 for safety; as/ld may want to use it to achieve the call to - * the code in mm/tlbmiss.c */ - st.q SP, TLB_SAVED_R25, r25 - gettr tr0, r2 - gettr tr1, r3 - gettr tr2, r4 - gettr tr3, r5 - gettr tr4, r18 - st.q SP, SAVED_TR0 , r2 - st.q SP, TLB_SAVED_TR1 , r3 - st.q SP, TLB_SAVED_TR2 , r4 - st.q SP, TLB_SAVED_TR3 , r5 - st.q SP, TLB_SAVED_TR4 , r18 - - pt do_fast_page_fault, tr0 - getcon SSR, r2 - getcon EXPEVT, r3 - getcon TEA, r4 - shlri r2, 30, r2 - andi r2, 1, r2 /* r2 = SSR.MD */ - blink tr0, LINK - - pt fixup_to_invoke_general_handler, tr1 - - /* If the fast path handler fixed the fault, just drop through quickly - to the restore code right away to return to the excepting context. - */ - beqi/u r2, 0, tr1 - -fast_tlb_miss_restore: - ld.q SP, SAVED_TR0, r2 - ld.q SP, TLB_SAVED_TR1, r3 - ld.q SP, TLB_SAVED_TR2, r4 - - ld.q SP, TLB_SAVED_TR3, r5 - ld.q SP, TLB_SAVED_TR4, r18 - - ptabs r2, tr0 - ptabs r3, tr1 - ptabs r4, tr2 - ptabs r5, tr3 - ptabs r18, tr4 - - ld.q SP, TLB_SAVED_R0, r0 - ld.q SP, TLB_SAVED_R1, r1 - ld.q SP, SAVED_R2, r2 - ld.q SP, SAVED_R3, r3 - ld.q SP, SAVED_R4, r4 - ld.q SP, SAVED_R5, r5 - ld.q SP, SAVED_R6, r6 - ld.q SP, SAVED_R18, r18 - ld.q SP, TLB_SAVED_R25, r25 - - getcon KCR1, SP - rte - nop /* for safety, in case the code is run on sh5-101 cut1.x */ - -fixup_to_invoke_general_handler: - - /* OK, new method. Restore stuff that's not expected to get saved into - the 'first-level' reg save area, then just fall through to setting - up the registers and calling the second-level handler. */ - - /* 2nd level expects r2,3,4,5,6,18,tr0 to be saved. So we must restore - r25,tr1-4 and save r6 to get into the right state. */ - - ld.q SP, TLB_SAVED_TR1, r3 - ld.q SP, TLB_SAVED_TR2, r4 - ld.q SP, TLB_SAVED_TR3, r5 - ld.q SP, TLB_SAVED_TR4, r18 - ld.q SP, TLB_SAVED_R25, r25 - - ld.q SP, TLB_SAVED_R0, r0 - ld.q SP, TLB_SAVED_R1, r1 - - ptabs/u r3, tr1 - ptabs/u r4, tr2 - ptabs/u r5, tr3 - ptabs/u r18, tr4 - - /* Set args for Non-debug, TLB miss class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_TLB, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - -/* NB TAKE GREAT CARE HERE TO ENSURE THAT THE INTERRUPT CODE - DOES END UP AT VBR+0x600 */ - nop - nop - nop - nop - nop - nop - - .balign 256 - /* VBR + 0x600 */ - -interrupt: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* Save original stack pointer into KCR1 */ - putcon SP, KCR1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for interrupt class handler */ - getcon INTEVT, r2 - movi ret_from_irq, r3 - ori r3, 1, r3 - movi EVENT_INTERRUPT, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - .balign TEXT_SIZE /* let's waste the bare minimum */ - -LVBR_block_end: /* Marker. Used for total checking */ - - .balign 256 -LRESVEC_block: - /* Panic handler. Called with MMU off. Possible causes/actions: - * - Reset: Jump to program start. - * - Single Step: Turn off Single Step & return. - * - Others: Call panic handler, passing PC as arg. - * (this may need to be extended...) - */ -reset_or_panic: - synco /* TAKum03020 (but probably a good idea anyway.) */ - putcon SP, DCR - /* First save r0-1 and tr0, as we need to use these */ - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - st.q SP, 0, r0 - st.q SP, 8, r1 - gettr tr0, r0 - st.q SP, 32, r0 - - /* Check cause */ - getcon EXPEVT, r0 - movi RESET_CAUSE, r1 - sub r1, r0, r1 /* r1=0 if reset */ - movi _stext-CONFIG_CACHED_MEMORY_OFFSET, r0 - ori r0, 1, r0 - ptabs r0, tr0 - beqi r1, 0, tr0 /* Jump to start address if reset */ - - getcon EXPEVT, r0 - movi DEBUGSS_CAUSE, r1 - sub r1, r0, r1 /* r1=0 if single step */ - pta single_step_panic, tr0 - beqi r1, 0, tr0 /* jump if single step */ - - /* Now jump to where we save the registers. */ - movi panic_stash_regs-CONFIG_CACHED_MEMORY_OFFSET, r1 - ptabs r1, tr0 - blink tr0, r63 - -single_step_panic: - /* We are in a handler with Single Step set. We need to resume the - * handler, by turning on MMU & turning off Single Step. */ - getcon SSR, r0 - movi SR_MMU, r1 - or r0, r1, r0 - movi ~SR_SS, r1 - and r0, r1, r0 - putcon r0, SSR - /* Restore EXPEVT, as the rte won't do this */ - getcon PEXPEVT, r0 - putcon r0, EXPEVT - /* Restore regs */ - ld.q SP, 32, r0 - ptabs r0, tr0 - ld.q SP, 0, r0 - ld.q SP, 8, r1 - getcon DCR, SP - synco - rte - - - .balign 256 -debug_exception: - synco /* TAKum03020 (but probably a good idea anyway.) */ - /* - * Single step/software_break_point first level handler. - * Called with MMU off, so the first thing we do is enable it - * by doing an rte with appropriate SSR. - */ - putcon SP, DCR - /* Save SSR & SPC, together with R0 & R1, as we need to use 2 regs. */ - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - - /* With the MMU off, we are bypassing the cache, so purge any - * data that will be made stale by the following stores. - */ - ocbp SP, 0 - synco - - st.q SP, 0, r0 - st.q SP, 8, r1 - getcon SPC, r0 - st.q SP, 16, r0 - getcon SSR, r0 - st.q SP, 24, r0 - - /* Enable MMU, block exceptions, set priv mode, disable single step */ - movi SR_MMU | SR_BL | SR_MD, r1 - or r0, r1, r0 - movi ~SR_SS, r1 - and r0, r1, r0 - putcon r0, SSR - /* Force control to debug_exception_2 when rte is executed */ - movi debug_exeception_2, r0 - ori r0, 1, r0 /* force SHmedia, just in case */ - putcon r0, SPC - getcon DCR, SP - synco - rte -debug_exeception_2: - /* Restore saved regs */ - putcon SP, KCR1 - movi resvec_save_area, SP - ld.q SP, 24, r0 - putcon r0, SSR - ld.q SP, 16, r0 - putcon r0, SPC - ld.q SP, 0, r0 - ld.q SP, 8, r1 - - /* Save other original registers into reg_save_area */ - movi reg_save_area, SP - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* Set args for debug class handler */ - getcon EXPEVT, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_DEBUG, r4 - or SP, ZERO, r5 - getcon KCR1, SP - pta handle_exception, tr0 - blink tr0, ZERO - - .balign 256 -debug_interrupt: - /* !!! WE COME HERE IN REAL MODE !!! */ - /* Hook-up debug interrupt to allow various debugging options to be - * hooked into its handler. */ - /* Save original stack pointer into KCR1 */ - synco - putcon SP, KCR1 - movi resvec_save_area-CONFIG_CACHED_MEMORY_OFFSET, SP - ocbp SP, 0 - ocbp SP, 32 - synco - - /* Save other original registers into reg_save_area thru real addresses */ - st.q SP, SAVED_R2, r2 - st.q SP, SAVED_R3, r3 - st.q SP, SAVED_R4, r4 - st.q SP, SAVED_R5, r5 - st.q SP, SAVED_R6, r6 - st.q SP, SAVED_R18, r18 - gettr tr0, r3 - st.q SP, SAVED_TR0, r3 - - /* move (spc,ssr)->(pspc,pssr). The rte will shift - them back again, so that they look like the originals - as far as the real handler code is concerned. */ - getcon spc, r6 - putcon r6, pspc - getcon ssr, r6 - putcon r6, pssr - - ! construct useful SR for handle_exception - movi 3, r6 - shlli r6, 30, r6 - getcon sr, r18 - or r18, r6, r6 - putcon r6, ssr - - ! SSR is now the current SR with the MD and MMU bits set - ! i.e. the rte will switch back to priv mode and put - ! the mmu back on - - ! construct spc - movi handle_exception, r18 - ori r18, 1, r18 ! for safety (do we need this?) - putcon r18, spc - - /* Set args for Non-debug, Not a TLB miss class handler */ - - ! EXPEVT==0x80 is unused, so 'steal' this value to put the - ! debug interrupt handler in the vectoring table - movi 0x80, r2 - movi ret_from_exception, r3 - ori r3, 1, r3 - movi EVENT_FAULT_NOT_TLB, r4 - - or SP, ZERO, r5 - movi CONFIG_CACHED_MEMORY_OFFSET, r6 - add r6, r5, r5 - getcon KCR1, SP - - synco ! for safety - rte ! -> handle_exception, switch back to priv mode again - -LRESVEC_block_end: /* Marker. Unused. */ - - .balign TEXT_SIZE - -/* - * Second level handler for VBR-based exceptions. Pre-handler. - * In common to all stack-frame sensitive handlers. - * - * Inputs: - * (KCR0) Current [current task union] - * (KCR1) Original SP - * (r2) INTEVT/EXPEVT - * (r3) appropriate return address - * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault, 3=debug) - * (r5) Pointer to reg_save_area - * (SP) Original SP - * - * Available registers: - * (r6) - * (r18) - * (tr0) - * - */ -handle_exception: - /* Common 2nd level handler. */ - - /* First thing we need an appropriate stack pointer */ - getcon SSR, r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta stack_ok, tr0 - bne r6, ZERO, tr0 /* Original stack pointer is fine */ - - /* Set stack pointer for user fault */ - getcon KCR0, SP - movi THREAD_SIZE, r6 /* Point to the end */ - add SP, r6, SP - -stack_ok: - -/* DEBUG : check for underflow/overflow of the kernel stack */ - pta no_underflow, tr0 - getcon KCR0, r6 - movi 1024, r18 - add r6, r18, r6 - bge SP, r6, tr0 ! ? below 1k from bottom of stack : danger zone - -/* Just panic to cause a crash. */ -bad_sp: - ld.b r63, 0, r6 - nop - -no_underflow: - pta bad_sp, tr0 - getcon kcr0, r6 - movi THREAD_SIZE, r18 - add r18, r6, r6 - bgt SP, r6, tr0 ! sp above the stack - - /* Make some room for the BASIC frame. */ - movi -(FRAME_SIZE), r6 - add SP, r6, SP - -/* Could do this with no stalling if we had another spare register, but the - code below will be OK. */ - ld.q r5, SAVED_R2, r6 - ld.q r5, SAVED_R3, r18 - st.q SP, FRAME_R(2), r6 - ld.q r5, SAVED_R4, r6 - st.q SP, FRAME_R(3), r18 - ld.q r5, SAVED_R5, r18 - st.q SP, FRAME_R(4), r6 - ld.q r5, SAVED_R6, r6 - st.q SP, FRAME_R(5), r18 - ld.q r5, SAVED_R18, r18 - st.q SP, FRAME_R(6), r6 - ld.q r5, SAVED_TR0, r6 - st.q SP, FRAME_R(18), r18 - st.q SP, FRAME_T(0), r6 - - /* Keep old SP around */ - getcon KCR1, r6 - - /* Save the rest of the general purpose registers */ - st.q SP, FRAME_R(0), r0 - st.q SP, FRAME_R(1), r1 - st.q SP, FRAME_R(7), r7 - st.q SP, FRAME_R(8), r8 - st.q SP, FRAME_R(9), r9 - st.q SP, FRAME_R(10), r10 - st.q SP, FRAME_R(11), r11 - st.q SP, FRAME_R(12), r12 - st.q SP, FRAME_R(13), r13 - st.q SP, FRAME_R(14), r14 - - /* SP is somewhere else */ - st.q SP, FRAME_R(15), r6 - - st.q SP, FRAME_R(16), r16 - st.q SP, FRAME_R(17), r17 - /* r18 is saved earlier. */ - st.q SP, FRAME_R(19), r19 - st.q SP, FRAME_R(20), r20 - st.q SP, FRAME_R(21), r21 - st.q SP, FRAME_R(22), r22 - st.q SP, FRAME_R(23), r23 - st.q SP, FRAME_R(24), r24 - st.q SP, FRAME_R(25), r25 - st.q SP, FRAME_R(26), r26 - st.q SP, FRAME_R(27), r27 - st.q SP, FRAME_R(28), r28 - st.q SP, FRAME_R(29), r29 - st.q SP, FRAME_R(30), r30 - st.q SP, FRAME_R(31), r31 - st.q SP, FRAME_R(32), r32 - st.q SP, FRAME_R(33), r33 - st.q SP, FRAME_R(34), r34 - st.q SP, FRAME_R(35), r35 - st.q SP, FRAME_R(36), r36 - st.q SP, FRAME_R(37), r37 - st.q SP, FRAME_R(38), r38 - st.q SP, FRAME_R(39), r39 - st.q SP, FRAME_R(40), r40 - st.q SP, FRAME_R(41), r41 - st.q SP, FRAME_R(42), r42 - st.q SP, FRAME_R(43), r43 - st.q SP, FRAME_R(44), r44 - st.q SP, FRAME_R(45), r45 - st.q SP, FRAME_R(46), r46 - st.q SP, FRAME_R(47), r47 - st.q SP, FRAME_R(48), r48 - st.q SP, FRAME_R(49), r49 - st.q SP, FRAME_R(50), r50 - st.q SP, FRAME_R(51), r51 - st.q SP, FRAME_R(52), r52 - st.q SP, FRAME_R(53), r53 - st.q SP, FRAME_R(54), r54 - st.q SP, FRAME_R(55), r55 - st.q SP, FRAME_R(56), r56 - st.q SP, FRAME_R(57), r57 - st.q SP, FRAME_R(58), r58 - st.q SP, FRAME_R(59), r59 - st.q SP, FRAME_R(60), r60 - st.q SP, FRAME_R(61), r61 - st.q SP, FRAME_R(62), r62 - - /* - * Save the S* registers. - */ - getcon SSR, r61 - st.q SP, FRAME_S(FSSR), r61 - getcon SPC, r62 - st.q SP, FRAME_S(FSPC), r62 - movi -1, r62 /* Reset syscall_nr */ - st.q SP, FRAME_S(FSYSCALL_ID), r62 - - /* Save the rest of the target registers */ - gettr tr1, r6 - st.q SP, FRAME_T(1), r6 - gettr tr2, r6 - st.q SP, FRAME_T(2), r6 - gettr tr3, r6 - st.q SP, FRAME_T(3), r6 - gettr tr4, r6 - st.q SP, FRAME_T(4), r6 - gettr tr5, r6 - st.q SP, FRAME_T(5), r6 - gettr tr6, r6 - st.q SP, FRAME_T(6), r6 - gettr tr7, r6 - st.q SP, FRAME_T(7), r6 - - ! setup FP so that unwinder can wind back through nested kernel mode - ! exceptions - add SP, ZERO, r14 - -#ifdef CONFIG_POOR_MANS_STRACE - /* We've pushed all the registers now, so only r2-r4 hold anything - * useful. Move them into callee save registers */ - or r2, ZERO, r28 - or r3, ZERO, r29 - or r4, ZERO, r30 - - /* Preserve r2 as the event code */ - movi evt_debug, r3 - ori r3, 1, r3 - ptabs r3, tr0 - - or SP, ZERO, r6 - getcon TRA, r5 - blink tr0, LINK - - or r28, ZERO, r2 - or r29, ZERO, r3 - or r30, ZERO, r4 -#endif - - /* For syscall and debug race condition, get TRA now */ - getcon TRA, r5 - - /* We are in a safe position to turn SR.BL off, but set IMASK=0xf - * Also set FD, to catch FPU usage in the kernel. - * - * benedict.gaster@superh.com 29/07/2002 - * - * On all SH5-101 revisions it is unsafe to raise the IMASK and at the - * same time change BL from 1->0, as any pending interrupt of a level - * higher than he previous value of IMASK will leak through and be - * taken unexpectedly. - * - * To avoid this we raise the IMASK and then issue another PUTCON to - * enable interrupts. - */ - getcon SR, r6 - movi SR_IMASK | SR_FD, r7 - or r6, r7, r6 - putcon r6, SR - movi SR_UNBLOCK_EXC, r7 - and r6, r7, r6 - putcon r6, SR - - - /* Now call the appropriate 3rd level handler */ - or r3, ZERO, LINK - movi trap_jtable, r3 - shlri r2, 3, r2 - ldx.l r2, r3, r3 - shlri r2, 2, r2 - ptabs r3, tr0 - or SP, ZERO, r3 - blink tr0, ZERO - -/* - * Second level handler for VBR-based exceptions. Post-handlers. - * - * Post-handlers for interrupts (ret_from_irq), exceptions - * (ret_from_exception) and common reentrance doors (restore_all - * to get back to the original context, ret_from_syscall loop to - * check kernel exiting). - * - * ret_with_reschedule and work_notifysig are an inner lables of - * the ret_from_syscall loop. - * - * In common to all stack-frame sensitive handlers. - * - * Inputs: - * (SP) struct pt_regs *, original register's frame pointer (basic) - * - */ - .global ret_from_irq -ret_from_irq: -#ifdef CONFIG_POOR_MANS_STRACE - pta evt_debug_ret_from_irq, tr0 - ori SP, 0, r2 - blink tr0, LINK -#endif - ld.q SP, FRAME_S(FSSR), r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta resume_kernel, tr0 - bne r6, ZERO, tr0 /* no further checks */ - STI() - pta ret_with_reschedule, tr0 - blink tr0, ZERO /* Do not check softirqs */ - - .global ret_from_exception -ret_from_exception: - preempt_stop() - -#ifdef CONFIG_POOR_MANS_STRACE - pta evt_debug_ret_from_exc, tr0 - ori SP, 0, r2 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSSR), r6 - shlri r6, 30, r6 - andi r6, 1, r6 - pta resume_kernel, tr0 - bne r6, ZERO, tr0 /* no further checks */ - - /* Check softirqs */ - -#ifdef CONFIG_PREEMPT - pta ret_from_syscall, tr0 - blink tr0, ZERO - -resume_kernel: - pta restore_all, tr0 - - getcon KCR0, r6 - ld.l r6, TI_PRE_COUNT, r7 - beq/u r7, ZERO, tr0 - -need_resched: - ld.l r6, TI_FLAGS, r7 - movi (1 << TIF_NEED_RESCHED), r8 - and r8, r7, r8 - bne r8, ZERO, tr0 - - getcon SR, r7 - andi r7, 0xf0, r7 - bne r7, ZERO, tr0 - - movi ((PREEMPT_ACTIVE >> 16) & 65535), r8 - shori (PREEMPT_ACTIVE & 65535), r8 - st.l r6, TI_PRE_COUNT, r8 - - STI() - movi schedule, r7 - ori r7, 1, r7 - ptabs r7, tr1 - blink tr1, LINK - - st.l r6, TI_PRE_COUNT, ZERO - CLI() - - pta need_resched, tr1 - blink tr1, ZERO -#endif - - .global ret_from_syscall -ret_from_syscall: - -ret_with_reschedule: - getcon KCR0, r6 ! r6 contains current_thread_info - ld.l r6, TI_FLAGS, r7 ! r7 contains current_thread_info->flags - - ! FIXME:!!! - ! no handling of TIF_SYSCALL_TRACE yet!! - - movi _TIF_NEED_RESCHED, r8 - and r8, r7, r8 - pta work_resched, tr0 - bne r8, ZERO, tr0 - - pta restore_all, tr1 - - movi (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8 - and r8, r7, r8 - pta work_notifysig, tr0 - bne r8, ZERO, tr0 - - blink tr1, ZERO - -work_resched: - pta ret_from_syscall, tr0 - gettr tr0, LINK - movi schedule, r6 - ptabs r6, tr0 - blink tr0, ZERO /* Call schedule(), return on top */ - -work_notifysig: - gettr tr1, LINK - - movi do_signal, r6 - ptabs r6, tr0 - or SP, ZERO, r2 - or ZERO, ZERO, r3 - blink tr0, LINK /* Call do_signal(regs, 0), return here */ - -restore_all: - /* Do prefetches */ - - ld.q SP, FRAME_T(0), r6 - ld.q SP, FRAME_T(1), r7 - ld.q SP, FRAME_T(2), r8 - ld.q SP, FRAME_T(3), r9 - ptabs r6, tr0 - ptabs r7, tr1 - ptabs r8, tr2 - ptabs r9, tr3 - ld.q SP, FRAME_T(4), r6 - ld.q SP, FRAME_T(5), r7 - ld.q SP, FRAME_T(6), r8 - ld.q SP, FRAME_T(7), r9 - ptabs r6, tr4 - ptabs r7, tr5 - ptabs r8, tr6 - ptabs r9, tr7 - - ld.q SP, FRAME_R(0), r0 - ld.q SP, FRAME_R(1), r1 - ld.q SP, FRAME_R(2), r2 - ld.q SP, FRAME_R(3), r3 - ld.q SP, FRAME_R(4), r4 - ld.q SP, FRAME_R(5), r5 - ld.q SP, FRAME_R(6), r6 - ld.q SP, FRAME_R(7), r7 - ld.q SP, FRAME_R(8), r8 - ld.q SP, FRAME_R(9), r9 - ld.q SP, FRAME_R(10), r10 - ld.q SP, FRAME_R(11), r11 - ld.q SP, FRAME_R(12), r12 - ld.q SP, FRAME_R(13), r13 - ld.q SP, FRAME_R(14), r14 - - ld.q SP, FRAME_R(16), r16 - ld.q SP, FRAME_R(17), r17 - ld.q SP, FRAME_R(18), r18 - ld.q SP, FRAME_R(19), r19 - ld.q SP, FRAME_R(20), r20 - ld.q SP, FRAME_R(21), r21 - ld.q SP, FRAME_R(22), r22 - ld.q SP, FRAME_R(23), r23 - ld.q SP, FRAME_R(24), r24 - ld.q SP, FRAME_R(25), r25 - ld.q SP, FRAME_R(26), r26 - ld.q SP, FRAME_R(27), r27 - ld.q SP, FRAME_R(28), r28 - ld.q SP, FRAME_R(29), r29 - ld.q SP, FRAME_R(30), r30 - ld.q SP, FRAME_R(31), r31 - ld.q SP, FRAME_R(32), r32 - ld.q SP, FRAME_R(33), r33 - ld.q SP, FRAME_R(34), r34 - ld.q SP, FRAME_R(35), r35 - ld.q SP, FRAME_R(36), r36 - ld.q SP, FRAME_R(37), r37 - ld.q SP, FRAME_R(38), r38 - ld.q SP, FRAME_R(39), r39 - ld.q SP, FRAME_R(40), r40 - ld.q SP, FRAME_R(41), r41 - ld.q SP, FRAME_R(42), r42 - ld.q SP, FRAME_R(43), r43 - ld.q SP, FRAME_R(44), r44 - ld.q SP, FRAME_R(45), r45 - ld.q SP, FRAME_R(46), r46 - ld.q SP, FRAME_R(47), r47 - ld.q SP, FRAME_R(48), r48 - ld.q SP, FRAME_R(49), r49 - ld.q SP, FRAME_R(50), r50 - ld.q SP, FRAME_R(51), r51 - ld.q SP, FRAME_R(52), r52 - ld.q SP, FRAME_R(53), r53 - ld.q SP, FRAME_R(54), r54 - ld.q SP, FRAME_R(55), r55 - ld.q SP, FRAME_R(56), r56 - ld.q SP, FRAME_R(57), r57 - ld.q SP, FRAME_R(58), r58 - - getcon SR, r59 - movi SR_BLOCK_EXC, r60 - or r59, r60, r59 - putcon r59, SR /* SR.BL = 1, keep nesting out */ - ld.q SP, FRAME_S(FSSR), r61 - ld.q SP, FRAME_S(FSPC), r62 - movi SR_ASID_MASK, r60 - and r59, r60, r59 - andc r61, r60, r61 /* Clear out older ASID */ - or r59, r61, r61 /* Retain current ASID */ - putcon r61, SSR - putcon r62, SPC - - /* Ignore FSYSCALL_ID */ - - ld.q SP, FRAME_R(59), r59 - ld.q SP, FRAME_R(60), r60 - ld.q SP, FRAME_R(61), r61 - ld.q SP, FRAME_R(62), r62 - - /* Last touch */ - ld.q SP, FRAME_R(15), SP - rte - nop - -/* - * Third level handlers for VBR-based exceptions. Adapting args to - * and/or deflecting to fourth level handlers. - * - * Fourth level handlers interface. - * Most are C-coded handlers directly pointed by the trap_jtable. - * (Third = Fourth level) - * Inputs: - * (r2) fault/interrupt code, entry number (e.g. NMI = 14, - * IRL0-3 (0000) = 16, RTLBMISS = 2, SYSCALL = 11, etc ...) - * (r3) struct pt_regs *, original register's frame pointer - * (r4) Event (0 = interrupt, 1 = TLB miss fault, 2 = Not TLB miss fault) - * (r5) TRA control register (for syscall/debug benefit only) - * (LINK) return address - * (SP) = r3 - * - * Kernel TLB fault handlers will get a slightly different interface. - * (r2) struct pt_regs *, original register's frame pointer - * (r3) writeaccess, whether it's a store fault as opposed to load fault - * (r4) execaccess, whether it's a ITLB fault as opposed to DTLB fault - * (r5) Effective Address of fault - * (LINK) return address - * (SP) = r2 - * - * fpu_error_or_IRQ? is a helper to deflect to the right cause. - * - */ -tlb_miss_load: - or SP, ZERO, r2 - or ZERO, ZERO, r3 /* Read */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 - pta call_do_page_fault, tr0 - beq ZERO, ZERO, tr0 - -tlb_miss_store: - or SP, ZERO, r2 - movi 1, r3 /* Write */ - or ZERO, ZERO, r4 /* Data */ - getcon TEA, r5 - pta call_do_page_fault, tr0 - beq ZERO, ZERO, tr0 - -itlb_miss_or_IRQ: - pta its_IRQ, tr0 - beqi/u r4, EVENT_INTERRUPT, tr0 - or SP, ZERO, r2 - or ZERO, ZERO, r3 /* Read */ - movi 1, r4 /* Text */ - getcon TEA, r5 - /* Fall through */ - -call_do_page_fault: - movi do_page_fault, r6 - ptabs r6, tr0 - blink tr0, ZERO - -fpu_error_or_IRQA: - pta its_IRQ, tr0 - beqi/l r4, EVENT_INTERRUPT, tr0 -#ifdef CONFIG_SH_FPU - movi do_fpu_state_restore, r6 -#else - movi do_exception_error, r6 -#endif - ptabs r6, tr0 - blink tr0, ZERO - -fpu_error_or_IRQB: - pta its_IRQ, tr0 - beqi/l r4, EVENT_INTERRUPT, tr0 -#ifdef CONFIG_SH_FPU - movi do_fpu_state_restore, r6 -#else - movi do_exception_error, r6 -#endif - ptabs r6, tr0 - blink tr0, ZERO - -its_IRQ: - movi do_IRQ, r6 - ptabs r6, tr0 - blink tr0, ZERO - -/* - * system_call/unknown_trap third level handler: - * - * Inputs: - * (r2) fault/interrupt code, entry number (TRAP = 11) - * (r3) struct pt_regs *, original register's frame pointer - * (r4) Not used. Event (0=interrupt, 1=TLB miss fault, 2=Not TLB miss fault) - * (r5) TRA Control Reg (0x00xyzzzz: x=1 SYSCALL, y = #args, z=nr) - * (SP) = r3 - * (LINK) return address: ret_from_exception - * (*r3) Syscall parms: SC#, arg0, arg1, ..., arg5 in order (Saved r2/r7) - * - * Outputs: - * (*r3) Syscall reply (Saved r2) - * (LINK) In case of syscall only it can be scrapped. - * Common second level post handler will be ret_from_syscall. - * Common (non-trace) exit point to that is syscall_ret (saving - * result to r2). Common bad exit point is syscall_bad (returning - * ENOSYS then saved to r2). - * - */ - -unknown_trap: - /* Unknown Trap or User Trace */ - movi do_unknown_trapa, r6 - ptabs r6, tr0 - ld.q r3, FRAME_R(9), r2 /* r2 = #arg << 16 | syscall # */ - andi r2, 0x1ff, r2 /* r2 = syscall # */ - blink tr0, LINK - - pta syscall_ret, tr0 - blink tr0, ZERO - - /* New syscall implementation*/ -system_call: - pta unknown_trap, tr0 - or r5, ZERO, r4 /* TRA (=r5) -> r4 */ - shlri r4, 20, r4 - bnei r4, 1, tr0 /* unknown_trap if not 0x1yzzzz */ - - /* It's a system call */ - st.q r3, FRAME_S(FSYSCALL_ID), r5 /* ID (0x1yzzzz) -> stack */ - andi r5, 0x1ff, r5 /* syscall # -> r5 */ - - STI() - - pta syscall_allowed, tr0 - movi NR_syscalls - 1, r4 /* Last valid */ - bgeu/l r4, r5, tr0 - -syscall_bad: - /* Return ENOSYS ! */ - movi -(ENOSYS), r2 /* Fall-through */ - - .global syscall_ret -syscall_ret: - st.q SP, FRAME_R(9), r2 /* Expecting SP back to BASIC frame */ - -#ifdef CONFIG_POOR_MANS_STRACE - /* nothing useful in registers at this point */ - - movi evt_debug2, r5 - ori r5, 1, r5 - ptabs r5, tr0 - ld.q SP, FRAME_R(9), r2 - or SP, ZERO, r3 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - pta ret_from_syscall, tr0 - blink tr0, ZERO - - -/* A different return path for ret_from_fork, because we now need - * to call schedule_tail with the later kernels. Because prev is - * loaded into r2 by switch_to() means we can just call it straight away - */ - -.global ret_from_fork -ret_from_fork: - - movi schedule_tail,r5 - ori r5, 1, r5 - ptabs r5, tr0 - blink tr0, LINK - -#ifdef CONFIG_POOR_MANS_STRACE - /* nothing useful in registers at this point */ - - movi evt_debug2, r5 - ori r5, 1, r5 - ptabs r5, tr0 - ld.q SP, FRAME_R(9), r2 - or SP, ZERO, r3 - blink tr0, LINK -#endif - - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - pta ret_from_syscall, tr0 - blink tr0, ZERO - - - -syscall_allowed: - /* Use LINK to deflect the exit point, default is syscall_ret */ - pta syscall_ret, tr0 - gettr tr0, LINK - pta syscall_notrace, tr0 - - getcon KCR0, r2 - ld.l r2, TI_FLAGS, r4 - movi (1 << TIF_SYSCALL_TRACE), r6 - and r6, r4, r6 - beq/l r6, ZERO, tr0 - - /* Trace it by calling syscall_trace before and after */ - movi syscall_trace, r4 - ptabs r4, tr0 - blink tr0, LINK - /* Reload syscall number as r5 is trashed by syscall_trace */ - ld.q SP, FRAME_S(FSYSCALL_ID), r5 - andi r5, 0x1ff, r5 - - pta syscall_ret_trace, tr0 - gettr tr0, LINK - -syscall_notrace: - /* Now point to the appropriate 4th level syscall handler */ - movi sys_call_table, r4 - shlli r5, 2, r5 - ldx.l r4, r5, r5 - ptabs r5, tr0 - - /* Prepare original args */ - ld.q SP, FRAME_R(2), r2 - ld.q SP, FRAME_R(3), r3 - ld.q SP, FRAME_R(4), r4 - ld.q SP, FRAME_R(5), r5 - ld.q SP, FRAME_R(6), r6 - ld.q SP, FRAME_R(7), r7 - - /* And now the trick for those syscalls requiring regs * ! */ - or SP, ZERO, r8 - - /* Call it */ - blink tr0, ZERO /* LINK is already properly set */ - -syscall_ret_trace: - /* We get back here only if under trace */ - st.q SP, FRAME_R(9), r2 /* Save return value */ - - movi syscall_trace, LINK - ptabs LINK, tr0 - blink tr0, LINK - - /* This needs to be done after any syscall tracing */ - ld.q SP, FRAME_S(FSPC), r2 - addi r2, 4, r2 /* Move PC, being pre-execution event */ - st.q SP, FRAME_S(FSPC), r2 - - pta ret_from_syscall, tr0 - blink tr0, ZERO /* Resume normal return sequence */ - -/* - * --- Switch to running under a particular ASID and return the previous ASID value - * --- The caller is assumed to have done a cli before calling this. - * - * Input r2 : new ASID - * Output r2 : old ASID - */ - - .global switch_and_save_asid -switch_and_save_asid: - getcon sr, r0 - movi 255, r4 - shlli r4, 16, r4 /* r4 = mask to select ASID */ - and r0, r4, r3 /* r3 = shifted old ASID */ - andi r2, 255, r2 /* mask down new ASID */ - shlli r2, 16, r2 /* align new ASID against SR.ASID */ - andc r0, r4, r0 /* efface old ASID from SR */ - or r0, r2, r0 /* insert the new ASID */ - putcon r0, ssr - movi 1f, r0 - putcon r0, spc - rte - nop -1: - ptabs LINK, tr0 - shlri r3, 16, r2 /* r2 = old ASID */ - blink tr0, r63 - - .global route_to_panic_handler -route_to_panic_handler: - /* Switch to real mode, goto panic_handler, don't return. Useful for - last-chance debugging, e.g. if no output wants to go to the console. - */ - - movi panic_handler - CONFIG_CACHED_MEMORY_OFFSET, r1 - ptabs r1, tr0 - pta 1f, tr1 - gettr tr1, r0 - putcon r0, spc - getcon sr, r0 - movi 1, r1 - shlli r1, 31, r1 - andc r0, r1, r0 - putcon r0, ssr - rte - nop -1: /* Now in real mode */ - blink tr0, r63 - nop - - .global peek_real_address_q -peek_real_address_q: - /* Two args: - r2 : real mode address to peek - r2(out) : result quadword - - This is provided as a cheapskate way of manipulating device - registers for debugging (to avoid the need to onchip_remap the debug - module, and to avoid the need to onchip_remap the watchpoint - controller in a way that identity maps sufficient bits to avoid the - SH5-101 cut2 silicon defect). - - This code is not performance critical - */ - - add.l r2, r63, r2 /* sign extend address */ - getcon sr, r0 /* r0 = saved original SR */ - movi 1, r1 - shlli r1, 28, r1 - or r0, r1, r1 /* r0 with block bit set */ - putcon r1, sr /* now in critical section */ - movi 1, r36 - shlli r36, 31, r36 - andc r1, r36, r1 /* turn sr.mmu off in real mode section */ - - putcon r1, ssr - movi .peek0 - CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */ - movi 1f, r37 /* virtual mode return addr */ - putcon r36, spc - - synco - rte - nop - -.peek0: /* come here in real mode, don't touch caches!! - still in critical section (sr.bl==1) */ - putcon r0, ssr - putcon r37, spc - /* Here's the actual peek. If the address is bad, all bets are now off - * what will happen (handlers invoked in real-mode = bad news) */ - ld.q r2, 0, r2 - synco - rte /* Back to virtual mode */ - nop - -1: - ptabs LINK, tr0 - blink tr0, r63 - - .global poke_real_address_q -poke_real_address_q: - /* Two args: - r2 : real mode address to poke - r3 : quadword value to write. - - This is provided as a cheapskate way of manipulating device - registers for debugging (to avoid the need to onchip_remap the debug - module, and to avoid the need to onchip_remap the watchpoint - controller in a way that identity maps sufficient bits to avoid the - SH5-101 cut2 silicon defect). - - This code is not performance critical - */ - - add.l r2, r63, r2 /* sign extend address */ - getcon sr, r0 /* r0 = saved original SR */ - movi 1, r1 - shlli r1, 28, r1 - or r0, r1, r1 /* r0 with block bit set */ - putcon r1, sr /* now in critical section */ - movi 1, r36 - shlli r36, 31, r36 - andc r1, r36, r1 /* turn sr.mmu off in real mode section */ - - putcon r1, ssr - movi .poke0-CONFIG_CACHED_MEMORY_OFFSET, r36 /* real mode target address */ - movi 1f, r37 /* virtual mode return addr */ - putcon r36, spc - - synco - rte - nop - -.poke0: /* come here in real mode, don't touch caches!! - still in critical section (sr.bl==1) */ - putcon r0, ssr - putcon r37, spc - /* Here's the actual poke. If the address is bad, all bets are now off - * what will happen (handlers invoked in real-mode = bad news) */ - st.q r2, 0, r3 - synco - rte /* Back to virtual mode */ - nop - -1: - ptabs LINK, tr0 - blink tr0, r63 - -/* - * --- User Access Handling Section - */ - -/* - * User Access support. It all moved to non inlined Assembler - * functions in here. - * - * __kernel_size_t __copy_user(void *__to, const void *__from, - * __kernel_size_t __n) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) size in bytes - * - * Ouputs: - * (*r2) target data - * (r2) non-copied bytes - * - * If a fault occurs on the user pointer, bail out early and return the - * number of bytes not copied in r2. - * Strategy : for large blocks, call a real memcpy function which can - * move >1 byte at a time using unaligned ld/st instructions, and can - * manipulate the cache using prefetch + alloco to improve the speed - * further. If a fault occurs in that function, just revert to the - * byte-by-byte approach used for small blocks; this is rare so the - * performance hit for that case does not matter. - * - * For small blocks it's not worth the overhead of setting up and calling - * the memcpy routine; do the copy a byte at a time. - * - */ - .global __copy_user -__copy_user: - pta __copy_user_byte_by_byte, tr1 - movi 16, r0 ! this value is a best guess, should tune it by benchmarking - bge/u r0, r4, tr1 - pta copy_user_memcpy, tr0 - addi SP, -32, SP - /* Save arguments in case we have to fix-up unhandled page fault */ - st.q SP, 0, r2 - st.q SP, 8, r3 - st.q SP, 16, r4 - st.q SP, 24, r35 ! r35 is callee-save - /* Save LINK in a register to reduce RTS time later (otherwise - ld SP,*,LINK;ptabs LINK;trn;blink trn,r63 becomes a critical path) */ - ori LINK, 0, r35 - blink tr0, LINK - - /* Copy completed normally if we get back here */ - ptabs r35, tr0 - ld.q SP, 24, r35 - /* don't restore r2-r4, pointless */ - /* set result=r2 to zero as the copy must have succeeded. */ - or r63, r63, r2 - addi SP, 32, SP - blink tr0, r63 ! RTS - - .global __copy_user_fixup -__copy_user_fixup: - /* Restore stack frame */ - ori r35, 0, LINK - ld.q SP, 24, r35 - ld.q SP, 16, r4 - ld.q SP, 8, r3 - ld.q SP, 0, r2 - addi SP, 32, SP - /* Fall through to original code, in the 'same' state we entered with */ - -/* The slow byte-by-byte method is used if the fast copy traps due to a bad - user address. In that rare case, the speed drop can be tolerated. */ -__copy_user_byte_by_byte: - pta ___copy_user_exit, tr1 - pta ___copy_user1, tr0 - beq/u r4, r63, tr1 /* early exit for zero length copy */ - sub r2, r3, r0 - addi r0, -1, r0 - -___copy_user1: - ld.b r3, 0, r5 /* Fault address 1 */ - - /* Could rewrite this to use just 1 add, but the second comes 'free' - due to load latency */ - addi r3, 1, r3 - addi r4, -1, r4 /* No real fixup required */ -___copy_user2: - stx.b r3, r0, r5 /* Fault address 2 */ - bne r4, ZERO, tr0 - -___copy_user_exit: - or r4, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * __kernel_size_t __clear_user(void *addr, __kernel_size_t size) - * - * Inputs: - * (r2) target address - * (r3) size in bytes - * - * Ouputs: - * (*r2) zero-ed target data - * (r2) non-zero-ed bytes - */ - .global __clear_user -__clear_user: - pta ___clear_user_exit, tr1 - pta ___clear_user1, tr0 - beq/u r3, r63, tr1 - -___clear_user1: - st.b r2, 0, ZERO /* Fault address */ - addi r2, 1, r2 - addi r3, -1, r3 /* No real fixup required */ - bne r3, ZERO, tr0 - -___clear_user_exit: - or r3, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - - -/* - * int __strncpy_from_user(unsigned long __dest, unsigned long __src, - * int __count) - * - * Inputs: - * (r2) target address - * (r3) source address - * (r4) maximum size in bytes - * - * Ouputs: - * (*r2) copied data - * (r2) -EFAULT (in case of faulting) - * copied data (otherwise) - */ - .global __strncpy_from_user -__strncpy_from_user: - pta ___strncpy_from_user1, tr0 - pta ___strncpy_from_user_done, tr1 - or r4, ZERO, r5 /* r5 = original count */ - beq/u r4, r63, tr1 /* early exit if r4==0 */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - -___strncpy_from_user1: - ld.b r3, 0, r7 /* Fault address: only in reading */ - st.b r2, 0, r7 - addi r2, 1, r2 - addi r3, 1, r3 - beq/u ZERO, r7, tr1 - addi r4, -1, r4 /* return real number of copied bytes */ - bne/l ZERO, r4, tr0 - -___strncpy_from_user_done: - sub r5, r4, r6 /* If done, return copied */ - -___strncpy_from_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __strnlen_user(const char *__s, long __n) - * - * Inputs: - * (r2) source address - * (r3) source size in bytes - * - * Ouputs: - * (r2) -EFAULT (in case of faulting) - * string length (otherwise) - */ - .global __strnlen_user -__strnlen_user: - pta ___strnlen_user_set_reply, tr0 - pta ___strnlen_user1, tr1 - or ZERO, ZERO, r5 /* r5 = counter */ - movi -(EFAULT), r6 /* r6 = reply, no real fixup */ - or ZERO, ZERO, r7 /* r7 = data, clear top byte of data */ - beq r3, ZERO, tr0 - -___strnlen_user1: - ldx.b r2, r5, r7 /* Fault address: only in reading */ - addi r3, -1, r3 /* No real fixup */ - addi r5, 1, r5 - beq r3, ZERO, tr0 - bne r7, ZERO, tr1 -! The line below used to be active. This meant led to a junk byte lying between each pair -! of entries in the argv & envp structures in memory. Whilst the program saw the right data -! via the argv and envp arguments to main, it meant the 'flat' representation visible through -! /proc/$pid/cmdline was corrupt, causing trouble with ps, for example. -! addi r5, 1, r5 /* Include '\0' */ - -___strnlen_user_set_reply: - or r5, ZERO, r6 /* If done, return counter */ - -___strnlen_user_exit: - or r6, ZERO, r2 - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __get_user_asm_?(void *val, long addr) - * - * Inputs: - * (r2) dest address - * (r3) source address (in User Space) - * - * Ouputs: - * (r2) -EFAULT (faulting) - * 0 (not faulting) - */ - .global __get_user_asm_b -__get_user_asm_b: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_b1: - ld.b r3, 0, r5 /* r5 = data */ - st.b r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_b_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_w -__get_user_asm_w: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_w1: - ld.w r3, 0, r5 /* r5 = data */ - st.w r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_w_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_l -__get_user_asm_l: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_l1: - ld.l r3, 0, r5 /* r5 = data */ - st.l r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_l_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __get_user_asm_q -__get_user_asm_q: - or r2, ZERO, r4 - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___get_user_asm_q1: - ld.q r3, 0, r5 /* r5 = data */ - st.q r4, 0, r5 - or ZERO, ZERO, r2 - -___get_user_asm_q_exit: - ptabs LINK, tr0 - blink tr0, ZERO - -/* - * extern long __put_user_asm_?(void *pval, long addr) - * - * Inputs: - * (r2) kernel pointer to value - * (r3) dest address (in User Space) - * - * Ouputs: - * (r2) -EFAULT (faulting) - * 0 (not faulting) - */ - .global __put_user_asm_b -__put_user_asm_b: - ld.b r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_b1: - st.b r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_b_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_w -__put_user_asm_w: - ld.w r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_w1: - st.w r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_w_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_l -__put_user_asm_l: - ld.l r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_l1: - st.l r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_l_exit: - ptabs LINK, tr0 - blink tr0, ZERO - - - .global __put_user_asm_q -__put_user_asm_q: - ld.q r2, 0, r4 /* r4 = data */ - movi -(EFAULT), r2 /* r2 = reply, no real fixup */ - -___put_user_asm_q1: - st.q r3, 0, r4 - or ZERO, ZERO, r2 - -___put_user_asm_q_exit: - ptabs LINK, tr0 - blink tr0, ZERO - -panic_stash_regs: - /* The idea is : when we get an unhandled panic, we dump the registers - to a known memory location, the just sit in a tight loop. - This allows the human to look at the memory region through the GDB - session (assuming the debug module's SHwy initiator isn't locked up - or anything), to hopefully analyze the cause of the panic. */ - - /* On entry, former r15 (SP) is in DCR - former r0 is at resvec_saved_area + 0 - former r1 is at resvec_saved_area + 8 - former tr0 is at resvec_saved_area + 32 - DCR is the only register whose value is lost altogether. - */ - - movi 0xffffffff80000000, r0 ! phy of dump area - ld.q SP, 0x000, r1 ! former r0 - st.q r0, 0x000, r1 - ld.q SP, 0x008, r1 ! former r1 - st.q r0, 0x008, r1 - st.q r0, 0x010, r2 - st.q r0, 0x018, r3 - st.q r0, 0x020, r4 - st.q r0, 0x028, r5 - st.q r0, 0x030, r6 - st.q r0, 0x038, r7 - st.q r0, 0x040, r8 - st.q r0, 0x048, r9 - st.q r0, 0x050, r10 - st.q r0, 0x058, r11 - st.q r0, 0x060, r12 - st.q r0, 0x068, r13 - st.q r0, 0x070, r14 - getcon dcr, r14 - st.q r0, 0x078, r14 - st.q r0, 0x080, r16 - st.q r0, 0x088, r17 - st.q r0, 0x090, r18 - st.q r0, 0x098, r19 - st.q r0, 0x0a0, r20 - st.q r0, 0x0a8, r21 - st.q r0, 0x0b0, r22 - st.q r0, 0x0b8, r23 - st.q r0, 0x0c0, r24 - st.q r0, 0x0c8, r25 - st.q r0, 0x0d0, r26 - st.q r0, 0x0d8, r27 - st.q r0, 0x0e0, r28 - st.q r0, 0x0e8, r29 - st.q r0, 0x0f0, r30 - st.q r0, 0x0f8, r31 - st.q r0, 0x100, r32 - st.q r0, 0x108, r33 - st.q r0, 0x110, r34 - st.q r0, 0x118, r35 - st.q r0, 0x120, r36 - st.q r0, 0x128, r37 - st.q r0, 0x130, r38 - st.q r0, 0x138, r39 - st.q r0, 0x140, r40 - st.q r0, 0x148, r41 - st.q r0, 0x150, r42 - st.q r0, 0x158, r43 - st.q r0, 0x160, r44 - st.q r0, 0x168, r45 - st.q r0, 0x170, r46 - st.q r0, 0x178, r47 - st.q r0, 0x180, r48 - st.q r0, 0x188, r49 - st.q r0, 0x190, r50 - st.q r0, 0x198, r51 - st.q r0, 0x1a0, r52 - st.q r0, 0x1a8, r53 - st.q r0, 0x1b0, r54 - st.q r0, 0x1b8, r55 - st.q r0, 0x1c0, r56 - st.q r0, 0x1c8, r57 - st.q r0, 0x1d0, r58 - st.q r0, 0x1d8, r59 - st.q r0, 0x1e0, r60 - st.q r0, 0x1e8, r61 - st.q r0, 0x1f0, r62 - st.q r0, 0x1f8, r63 ! bogus, but for consistency's sake... - - ld.q SP, 0x020, r1 ! former tr0 - st.q r0, 0x200, r1 - gettr tr1, r1 - st.q r0, 0x208, r1 - gettr tr2, r1 - st.q r0, 0x210, r1 - gettr tr3, r1 - st.q r0, 0x218, r1 - gettr tr4, r1 - st.q r0, 0x220, r1 - gettr tr5, r1 - st.q r0, 0x228, r1 - gettr tr6, r1 - st.q r0, 0x230, r1 - gettr tr7, r1 - st.q r0, 0x238, r1 - - getcon sr, r1 - getcon ssr, r2 - getcon pssr, r3 - getcon spc, r4 - getcon pspc, r5 - getcon intevt, r6 - getcon expevt, r7 - getcon pexpevt, r8 - getcon tra, r9 - getcon tea, r10 - getcon kcr0, r11 - getcon kcr1, r12 - getcon vbr, r13 - getcon resvec, r14 - - st.q r0, 0x240, r1 - st.q r0, 0x248, r2 - st.q r0, 0x250, r3 - st.q r0, 0x258, r4 - st.q r0, 0x260, r5 - st.q r0, 0x268, r6 - st.q r0, 0x270, r7 - st.q r0, 0x278, r8 - st.q r0, 0x280, r9 - st.q r0, 0x288, r10 - st.q r0, 0x290, r11 - st.q r0, 0x298, r12 - st.q r0, 0x2a0, r13 - st.q r0, 0x2a8, r14 - - getcon SPC,r2 - getcon SSR,r3 - getcon EXPEVT,r4 - /* Prepare to jump to C - physical address */ - movi panic_handler-CONFIG_CACHED_MEMORY_OFFSET, r1 - ori r1, 1, r1 - ptabs r1, tr0 - getcon DCR, SP - blink tr0, ZERO - nop - nop - nop - nop - - - - -/* - * --- Signal Handling Section - */ - -/* - * extern long long _sa_default_rt_restorer - * extern long long _sa_default_restorer - * - * or, better, - * - * extern void _sa_default_rt_restorer(void) - * extern void _sa_default_restorer(void) - * - * Code prototypes to do a sys_rt_sigreturn() or sys_sysreturn() - * from user space. Copied into user space by signal management. - * Both must be quad aligned and 2 quad long (4 instructions). - * - */ - .balign 8 - .global sa_default_rt_restorer -sa_default_rt_restorer: - movi 0x10, r9 - shori __NR_rt_sigreturn, r9 - trapa r9 - nop - - .balign 8 - .global sa_default_restorer -sa_default_restorer: - movi 0x10, r9 - shori __NR_sigreturn, r9 - trapa r9 - nop - -/* - * --- __ex_table Section - */ - -/* - * User Access Exception Table. - */ - .section __ex_table, "a" - - .global asm_uaccess_start /* Just a marker */ -asm_uaccess_start: - - .long ___copy_user1, ___copy_user_exit - .long ___copy_user2, ___copy_user_exit - .long ___clear_user1, ___clear_user_exit - .long ___strncpy_from_user1, ___strncpy_from_user_exit - .long ___strnlen_user1, ___strnlen_user_exit - .long ___get_user_asm_b1, ___get_user_asm_b_exit - .long ___get_user_asm_w1, ___get_user_asm_w_exit - .long ___get_user_asm_l1, ___get_user_asm_l_exit - .long ___get_user_asm_q1, ___get_user_asm_q_exit - .long ___put_user_asm_b1, ___put_user_asm_b_exit - .long ___put_user_asm_w1, ___put_user_asm_w_exit - .long ___put_user_asm_l1, ___put_user_asm_l_exit - .long ___put_user_asm_q1, ___put_user_asm_q_exit - - .global asm_uaccess_end /* Just a marker */ -asm_uaccess_end: - - - - -/* - * --- .text.init Section - */ - - .section .text.init, "ax" - -/* - * void trap_init (void) - * - */ - .global trap_init -trap_init: - addi SP, -24, SP /* Room to save r28/r29/r30 */ - st.q SP, 0, r28 - st.q SP, 8, r29 - st.q SP, 16, r30 - - /* Set VBR and RESVEC */ - movi LVBR_block, r19 - andi r19, -4, r19 /* reset MMUOFF + reserved */ - /* For RESVEC exceptions we force the MMU off, which means we need the - physical address. */ - movi LRESVEC_block-CONFIG_CACHED_MEMORY_OFFSET, r20 - andi r20, -4, r20 /* reset reserved */ - ori r20, 1, r20 /* set MMUOFF */ - putcon r19, VBR - putcon r20, RESVEC - - /* Sanity check */ - movi LVBR_block_end, r21 - andi r21, -4, r21 - movi BLOCK_SIZE, r29 /* r29 = expected size */ - or r19, ZERO, r30 - add r19, r29, r19 - - /* - * Ugly, but better loop forever now than crash afterwards. - * We should print a message, but if we touch LVBR or - * LRESVEC blocks we should not be surprised if we get stuck - * in trap_init(). - */ - pta trap_init_loop, tr1 - gettr tr1, r28 /* r28 = trap_init_loop */ - sub r21, r30, r30 /* r30 = actual size */ - - /* - * VBR/RESVEC handlers overlap by being bigger than - * allowed. Very bad. Just loop forever. - * (r28) panic/loop address - * (r29) expected size - * (r30) actual size - */ -trap_init_loop: - bne r19, r21, tr1 - - /* Now that exception vectors are set up reset SR.BL */ - getcon SR, r22 - movi SR_UNBLOCK_EXC, r23 - and r22, r23, r22 - putcon r22, SR - - addi SP, 24, SP - ptabs LINK, tr0 - blink tr0, ZERO - diff -puN arch/sh64/kernel/fpu.c~git-sh /dev/null --- a/arch/sh64/kernel/fpu.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/fpu.c - * - * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli - * Copyright (C) 2002 STMicroelectronics Limited - * Author : Stuart Menefy - * - * Started from SH4 version: - * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - */ - -#include -#include -#include -#include -#include - -/* - * Initially load the FPU with signalling NANS. This bit pattern - * has the property that no matter whether considered as single or as - * double precision, it still represents a signalling NAN. - */ -#define sNAN64 0xFFFFFFFFFFFFFFFFULL -#define sNAN32 0xFFFFFFFFUL - -static union sh_fpu_union init_fpuregs = { - .hard = { - .fp_regs = { [0 ... 63] = sNAN32 }, - .fpscr = FPSCR_INIT - } -}; - -inline void fpsave(struct sh_fpu_hard_struct *fpregs) -{ - asm volatile("fst.p %0, (0*8), fp0\n\t" - "fst.p %0, (1*8), fp2\n\t" - "fst.p %0, (2*8), fp4\n\t" - "fst.p %0, (3*8), fp6\n\t" - "fst.p %0, (4*8), fp8\n\t" - "fst.p %0, (5*8), fp10\n\t" - "fst.p %0, (6*8), fp12\n\t" - "fst.p %0, (7*8), fp14\n\t" - "fst.p %0, (8*8), fp16\n\t" - "fst.p %0, (9*8), fp18\n\t" - "fst.p %0, (10*8), fp20\n\t" - "fst.p %0, (11*8), fp22\n\t" - "fst.p %0, (12*8), fp24\n\t" - "fst.p %0, (13*8), fp26\n\t" - "fst.p %0, (14*8), fp28\n\t" - "fst.p %0, (15*8), fp30\n\t" - "fst.p %0, (16*8), fp32\n\t" - "fst.p %0, (17*8), fp34\n\t" - "fst.p %0, (18*8), fp36\n\t" - "fst.p %0, (19*8), fp38\n\t" - "fst.p %0, (20*8), fp40\n\t" - "fst.p %0, (21*8), fp42\n\t" - "fst.p %0, (22*8), fp44\n\t" - "fst.p %0, (23*8), fp46\n\t" - "fst.p %0, (24*8), fp48\n\t" - "fst.p %0, (25*8), fp50\n\t" - "fst.p %0, (26*8), fp52\n\t" - "fst.p %0, (27*8), fp54\n\t" - "fst.p %0, (28*8), fp56\n\t" - "fst.p %0, (29*8), fp58\n\t" - "fst.p %0, (30*8), fp60\n\t" - "fst.p %0, (31*8), fp62\n\t" - - "fgetscr fr63\n\t" - "fst.s %0, (32*8), fr63\n\t" - : /* no output */ - : "r" (fpregs) - : "memory"); -} - - -static inline void -fpload(struct sh_fpu_hard_struct *fpregs) -{ - asm volatile("fld.p %0, (0*8), fp0\n\t" - "fld.p %0, (1*8), fp2\n\t" - "fld.p %0, (2*8), fp4\n\t" - "fld.p %0, (3*8), fp6\n\t" - "fld.p %0, (4*8), fp8\n\t" - "fld.p %0, (5*8), fp10\n\t" - "fld.p %0, (6*8), fp12\n\t" - "fld.p %0, (7*8), fp14\n\t" - "fld.p %0, (8*8), fp16\n\t" - "fld.p %0, (9*8), fp18\n\t" - "fld.p %0, (10*8), fp20\n\t" - "fld.p %0, (11*8), fp22\n\t" - "fld.p %0, (12*8), fp24\n\t" - "fld.p %0, (13*8), fp26\n\t" - "fld.p %0, (14*8), fp28\n\t" - "fld.p %0, (15*8), fp30\n\t" - "fld.p %0, (16*8), fp32\n\t" - "fld.p %0, (17*8), fp34\n\t" - "fld.p %0, (18*8), fp36\n\t" - "fld.p %0, (19*8), fp38\n\t" - "fld.p %0, (20*8), fp40\n\t" - "fld.p %0, (21*8), fp42\n\t" - "fld.p %0, (22*8), fp44\n\t" - "fld.p %0, (23*8), fp46\n\t" - "fld.p %0, (24*8), fp48\n\t" - "fld.p %0, (25*8), fp50\n\t" - "fld.p %0, (26*8), fp52\n\t" - "fld.p %0, (27*8), fp54\n\t" - "fld.p %0, (28*8), fp56\n\t" - "fld.p %0, (29*8), fp58\n\t" - "fld.p %0, (30*8), fp60\n\t" - - "fld.s %0, (32*8), fr63\n\t" - "fputscr fr63\n\t" - - "fld.p %0, (31*8), fp62\n\t" - : /* no output */ - : "r" (fpregs) ); -} - -void fpinit(struct sh_fpu_hard_struct *fpregs) -{ - *fpregs = init_fpuregs.hard; -} - -asmlinkage void -do_fpu_error(unsigned long ex, struct pt_regs *regs) -{ - struct task_struct *tsk = current; - - regs->pc += 4; - - tsk->thread.trap_no = 11; - tsk->thread.error_code = 0; - force_sig(SIGFPE, tsk); -} - - -asmlinkage void -do_fpu_state_restore(unsigned long ex, struct pt_regs *regs) -{ - void die(const char *str, struct pt_regs *regs, long err); - - if (! user_mode(regs)) - die("FPU used in kernel", regs, ex); - - regs->sr &= ~SR_FD; - - if (last_task_used_math == current) - return; - - grab_fpu(); - if (last_task_used_math != NULL) { - /* Other processes fpu state, save away */ - fpsave(&last_task_used_math->thread.fpu.hard); - } - last_task_used_math = current; - if (used_math()) { - fpload(¤t->thread.fpu.hard); - } else { - /* First time FPU user. */ - fpload(&init_fpuregs.hard); - set_used_math(); - } - release_fpu(); -} - diff -puN arch/sh64/kernel/head.S~git-sh /dev/null --- a/arch/sh64/kernel/head.S +++ /dev/null @@ -1,372 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/head.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * - * benedict.gaster@superh.com: 2nd May 2002 - * Moved definition of empty_zero_page to its own section allowing - * it to be placed at an absolute address known at load time. - * - * lethal@linux-sh.org: 9th May 2003 - * Kill off GLOBAL_NAME() usage. - * - * lethal@linux-sh.org: 8th May 2004 - * Add early SCIF console DTLB mapping. - */ - - -#include -#include -#include -#include -#include -#include -#include - -/* - * MMU defines: TLB boundaries. - */ - -#define MMUIR_FIRST ITLB_FIXED -#define MMUIR_END ITLB_LAST_VAR_UNRESTRICTED+TLB_STEP -#define MMUIR_STEP TLB_STEP - -#define MMUDR_FIRST DTLB_FIXED -#define MMUDR_END DTLB_LAST_VAR_UNRESTRICTED+TLB_STEP -#define MMUDR_STEP TLB_STEP - -/* Safety check : CONFIG_CACHED_MEMORY_OFFSET has to be a multiple of 512Mb */ -#if (CONFIG_CACHED_MEMORY_OFFSET & ((1UL<<29)-1)) -#error "CONFIG_CACHED_MEMORY_OFFSET must be a multiple of 512Mb" -#endif - -/* - * MMU defines: Fixed TLBs. - */ -/* Deal safely with the case where the base of RAM is not 512Mb aligned */ - -#define ALIGN_512M_MASK (0xffffffffe0000000) -#define ALIGNED_EFFECTIVE ((CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START) & ALIGN_512M_MASK) -#define ALIGNED_PHYSICAL (CONFIG_MEMORY_START & ALIGN_512M_MASK) - -#define MMUIR_TEXT_H (0x0000000000000003 | ALIGNED_EFFECTIVE) - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ - -#define MMUIR_TEXT_L (0x000000000000009a | ALIGNED_PHYSICAL) - /* 512 Mb, Cacheable, Write-back, execute, Not User, Ph. Add. */ - -#define MMUDR_CACHED_H 0x0000000000000003 | ALIGNED_EFFECTIVE - /* Enabled, Shared, ASID 0, Eff. Add. 0xA0000000 */ -#define MMUDR_CACHED_L 0x000000000000015a | ALIGNED_PHYSICAL - /* 512 Mb, Cacheable, Write-back, read/write, Not User, Ph. Add. */ - -#ifdef CONFIG_ICACHE_DISABLED -#define ICCR0_INIT_VAL ICCR0_OFF /* ICACHE off */ -#else -#define ICCR0_INIT_VAL ICCR0_ON | ICCR0_ICI /* ICE + ICI */ -#endif -#define ICCR1_INIT_VAL ICCR1_NOLOCK /* No locking */ - -#if defined (CONFIG_DCACHE_DISABLED) -#define OCCR0_INIT_VAL OCCR0_OFF /* D-cache: off */ -#elif defined (CONFIG_DCACHE_WRITE_THROUGH) -#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WT /* D-cache: on, */ - /* WT, invalidate */ -#elif defined (CONFIG_DCACHE_WRITE_BACK) -#define OCCR0_INIT_VAL OCCR0_ON | OCCR0_OCI | OCCR0_WB /* D-cache: on, */ - /* WB, invalidate */ -#else -#error preprocessor flag CONFIG_DCACHE_... not recognized! -#endif - -#define OCCR1_INIT_VAL OCCR1_NOLOCK /* No locking */ - - .section .empty_zero_page, "aw" - .global empty_zero_page - -empty_zero_page: - .long 1 /* MOUNT_ROOT_RDONLY */ - .long 0 /* RAMDISK_FLAGS */ - .long 0x0200 /* ORIG_ROOT_DEV */ - .long 1 /* LOADER_TYPE */ - .long 0x00800000 /* INITRD_START */ - .long 0x00800000 /* INITRD_SIZE */ - .long 0 - - .text - .balign 4096,0,4096 - - .section .data, "aw" - .balign PAGE_SIZE - - .section .data, "aw" - .balign PAGE_SIZE - - .global swapper_pg_dir -swapper_pg_dir: - .space PAGE_SIZE, 0 - - .global empty_bad_page -empty_bad_page: - .space PAGE_SIZE, 0 - - .global empty_bad_pte_table -empty_bad_pte_table: - .space PAGE_SIZE, 0 - - .global fpu_in_use -fpu_in_use: .quad 0 - - - .section .text.head, "ax" - .balign L1_CACHE_BYTES -/* - * Condition at the entry of __stext: - * . Reset state: - * . SR.FD = 1 (FPU disabled) - * . SR.BL = 1 (Exceptions disabled) - * . SR.MD = 1 (Privileged Mode) - * . SR.MMU = 0 (MMU Disabled) - * . SR.CD = 0 (CTC User Visible) - * . SR.IMASK = Undefined (Interrupt Mask) - * - * Operations supposed to be performed by __stext: - * . prevent speculative fetch onto device memory while MMU is off - * . reflect as much as possible SH5 ABI (r15, r26, r27, r18) - * . first, save CPU state and set it to something harmless - * . any CPU detection and/or endianness settings (?) - * . initialize EMI/LMI (but not TMU/RTC/INTC/SCIF): TBD - * . set initial TLB entries for cached and uncached regions - * (no fine granularity paging) - * . set initial cache state - * . enable MMU and caches - * . set CPU to a consistent state - * . registers (including stack pointer and current/KCR0) - * . NOT expecting to set Exception handling nor VBR/RESVEC/DCR - * at this stage. This is all to later Linux initialization steps. - * . initialize FPU - * . clear BSS - * . jump into start_kernel() - * . be prepared to hopeless start_kernel() returns. - * - */ - .global _stext -_stext: - /* - * Prevent speculative fetch on device memory due to - * uninitialized target registers. - */ - ptabs/u ZERO, tr0 - ptabs/u ZERO, tr1 - ptabs/u ZERO, tr2 - ptabs/u ZERO, tr3 - ptabs/u ZERO, tr4 - ptabs/u ZERO, tr5 - ptabs/u ZERO, tr6 - ptabs/u ZERO, tr7 - synci - - /* - * Read/Set CPU state. After this block: - * r29 = Initial SR - */ - getcon SR, r29 - movi SR_HARMLESS, r20 - putcon r20, SR - - /* - * Initialize EMI/LMI. To Be Done. - */ - - /* - * CPU detection and/or endianness settings (?). To Be Done. - * Pure PIC code here, please ! Just save state into r30. - * After this block: - * r30 = CPU type/Platform Endianness - */ - - /* - * Set initial TLB entries for cached and uncached regions. - * Note: PTA/BLINK is PIC code, PTABS/BLINK isn't ! - */ - /* Clear ITLBs */ - pta clear_ITLB, tr1 - movi MMUIR_FIRST, r21 - movi MMUIR_END, r22 -clear_ITLB: - putcfg r21, 0, ZERO /* Clear MMUIR[n].PTEH.V */ - addi r21, MMUIR_STEP, r21 - bne r21, r22, tr1 - - /* Clear DTLBs */ - pta clear_DTLB, tr1 - movi MMUDR_FIRST, r21 - movi MMUDR_END, r22 -clear_DTLB: - putcfg r21, 0, ZERO /* Clear MMUDR[n].PTEH.V */ - addi r21, MMUDR_STEP, r21 - bne r21, r22, tr1 - - /* Map one big (512Mb) page for ITLB */ - movi MMUIR_FIRST, r21 - movi MMUIR_TEXT_L, r22 /* PTEL first */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 1, r22 /* Set MMUIR[0].PTEL */ - movi MMUIR_TEXT_H, r22 /* PTEH last */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 0, r22 /* Set MMUIR[0].PTEH */ - - /* Map one big CACHED (512Mb) page for DTLB */ - movi MMUDR_FIRST, r21 - movi MMUDR_CACHED_L, r22 /* PTEL first */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 1, r22 /* Set MMUDR[0].PTEL */ - movi MMUDR_CACHED_H, r22 /* PTEH last */ - add.l r22, r63, r22 /* Sign extend */ - putcfg r21, 0, r22 /* Set MMUDR[0].PTEH */ - -#ifdef CONFIG_EARLY_PRINTK - /* - * Setup a DTLB translation for SCIF phys. - */ - addi r21, MMUDR_STEP, r21 - movi 0x0a03, r22 /* SCIF phys */ - shori 0x0148, r22 - putcfg r21, 1, r22 /* PTEL first */ - movi 0xfa03, r22 /* 0xfa030000, fixed SCIF virt */ - shori 0x0003, r22 - putcfg r21, 0, r22 /* PTEH last */ -#endif - - /* - * Set cache behaviours. - */ - /* ICache */ - movi ICCR_BASE, r21 - movi ICCR0_INIT_VAL, r22 - movi ICCR1_INIT_VAL, r23 - putcfg r21, ICCR_REG0, r22 - putcfg r21, ICCR_REG1, r23 - - /* OCache */ - movi OCCR_BASE, r21 - movi OCCR0_INIT_VAL, r22 - movi OCCR1_INIT_VAL, r23 - putcfg r21, OCCR_REG0, r22 - putcfg r21, OCCR_REG1, r23 - - - /* - * Enable Caches and MMU. Do the first non-PIC jump. - * Now head.S global variables, constants and externs - * can be used. - */ - getcon SR, r21 - movi SR_ENABLE_MMU, r22 - or r21, r22, r21 - putcon r21, SSR - movi hyperspace, r22 - ori r22, 1, r22 /* Make it SHmedia, not required but..*/ - putcon r22, SPC - synco - rte /* And now go into the hyperspace ... */ -hyperspace: /* ... that's the next instruction ! */ - - /* - * Set CPU to a consistent state. - * r31 = FPU support flag - * tr0/tr7 in use. Others give a chance to loop somewhere safe - */ - movi start_kernel, r32 - ori r32, 1, r32 - - ptabs r32, tr0 /* r32 = _start_kernel address */ - pta/u hopeless, tr1 - pta/u hopeless, tr2 - pta/u hopeless, tr3 - pta/u hopeless, tr4 - pta/u hopeless, tr5 - pta/u hopeless, tr6 - pta/u hopeless, tr7 - gettr tr1, r28 /* r28 = hopeless address */ - - /* Set initial stack pointer */ - movi init_thread_union, SP - putcon SP, KCR0 /* Set current to init_task */ - movi THREAD_SIZE, r22 /* Point to the end */ - add SP, r22, SP - - /* - * Initialize FPU. - * Keep FPU flag in r31. After this block: - * r31 = FPU flag - */ - movi fpu_in_use, r31 /* Temporary */ - -#ifdef CONFIG_SH_FPU - getcon SR, r21 - movi SR_ENABLE_FPU, r22 - and r21, r22, r22 - putcon r22, SR /* Try to enable */ - getcon SR, r22 - xor r21, r22, r21 - shlri r21, 15, r21 /* Supposedly 0/1 */ - st.q r31, 0 , r21 /* Set fpu_in_use */ -#else - movi 0, r21 - st.q r31, 0 , r21 /* Set fpu_in_use */ -#endif - or r21, ZERO, r31 /* Set FPU flag at last */ - -#ifndef CONFIG_SH_NO_BSS_INIT -/* Don't clear BSS if running on slow platforms such as an RTL simulation, - remote memory via SHdebug link, etc. For these the memory can be guaranteed - to be all zero on boot anyway. */ - /* - * Clear bss - */ - pta clear_quad, tr1 - movi __bss_start, r22 - movi _end, r23 -clear_quad: - st.q r22, 0, ZERO - addi r22, 8, r22 - bne r22, r23, tr1 /* Both quad aligned, see vmlinux.lds.S */ -#endif - pta/u hopeless, tr1 - - /* Say bye to head.S but be prepared to wrongly get back ... */ - blink tr0, LINK - - /* If we ever get back here through LINK/tr1-tr7 */ - pta/u hopeless, tr7 - -hopeless: - /* - * Something's badly wrong here. Loop endlessly, - * there's nothing more we can do about it. - * - * Note on hopeless: it can be jumped into invariably - * before or after jumping into hyperspace. The only - * requirement is to be PIC called (PTA) before and - * any way (PTA/PTABS) after. According to Virtual - * to Physical mapping a simulator/emulator can easily - * tell where we came here from just looking at hopeless - * (PC) address. - * - * For debugging purposes: - * (r28) hopeless/loop address - * (r29) Original SR - * (r30) CPU type/Platform endianness - * (r31) FPU Support - * (r32) _start_kernel address - */ - blink tr7, ZERO - - diff -puN arch/sh64/kernel/init_task.c~git-sh /dev/null --- a/arch/sh64/kernel/init_task.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/init_task.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ -#include -#include -#include -#include -#include -#include -#include -#include - -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); - -struct pt_regs fake_swapper_regs; - -/* - * Initial thread structure. - * - * We need to make sure that this is THREAD_SIZE-byte 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); - diff -puN arch/sh64/kernel/irq.c~git-sh /dev/null --- a/arch/sh64/kernel/irq.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/irq.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -/* - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void ack_bad_irq(unsigned int irq) -{ - printk("unexpected IRQ trap at irq %02x\n", irq); -} - -#if defined(CONFIG_PROC_FS) -int show_interrupts(struct seq_file *p, void *v) -{ - int i = *(loff_t *) v, j; - struct irqaction * action; - unsigned long flags; - - if (i == 0) { - seq_puts(p, " "); - for_each_online_cpu(j) - seq_printf(p, "CPU%d ",j); - seq_putc(p, '\n'); - } - - if (i < NR_IRQS) { - spin_lock_irqsave(&irq_desc[i].lock, flags); - action = irq_desc[i].action; - if (!action) - goto unlock; - seq_printf(p, "%3d: ",i); - seq_printf(p, "%10u ", kstat_irqs(i)); - seq_printf(p, " %14s", irq_desc[i].chip->typename); - seq_printf(p, " %s", action->name); - - for (action=action->next; action; action = action->next) - seq_printf(p, ", %s", action->name); - seq_putc(p, '\n'); -unlock: - spin_unlock_irqrestore(&irq_desc[i].lock, flags); - } - return 0; -} -#endif - -/* - * do_NMI handles all Non-Maskable Interrupts. - */ -asmlinkage void do_NMI(unsigned long vector_num, struct pt_regs * regs) -{ - if (regs->sr & 0x40000000) - printk("unexpected NMI trap in system mode\n"); - else - printk("unexpected NMI trap in user mode\n"); - - /* No statistics */ -} - -/* - * do_IRQ handles all normal device IRQ's. - */ -asmlinkage int do_IRQ(unsigned long vector_num, struct pt_regs * regs) -{ - struct pt_regs *old_regs = set_irq_regs(regs); - int irq; - - irq_enter(); - - irq = irq_demux(vector_num); - - if (irq >= 0) { - __do_IRQ(irq); - } else { - printk("unexpected IRQ trap at vector %03lx\n", vector_num); - } - - irq_exit(); - - set_irq_regs(old_regs); - return 1; -} - diff -puN arch/sh64/kernel/irq_intc.c~git-sh /dev/null --- a/arch/sh64/kernel/irq_intc.c +++ /dev/null @@ -1,272 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/irq_intc.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * Interrupt Controller support for SH5 INTC. - * Per-interrupt selective. IRLM=0 (Fixed priority) is not - * supported being useless without a cascaded interrupt - * controller. - * - */ - -#include -#include -#include -#include -#include -#include /* this includes also -#include -#include -#include -#include - -/* - * Maybe the generic Peripheral block could move to a more - * generic include file. INTC Block will be defined here - * and only here to make INTC self-contained in a single - * file. - */ -#define INTC_BLOCK_OFFSET 0x01000000 - -/* Base */ -#define INTC_BASE PHYS_PERIPHERAL_BLOCK + \ - INTC_BLOCK_OFFSET - -/* Address */ -#define INTC_ICR_SET (intc_virt + 0x0) -#define INTC_ICR_CLEAR (intc_virt + 0x8) -#define INTC_INTPRI_0 (intc_virt + 0x10) -#define INTC_INTSRC_0 (intc_virt + 0x50) -#define INTC_INTSRC_1 (intc_virt + 0x58) -#define INTC_INTREQ_0 (intc_virt + 0x60) -#define INTC_INTREQ_1 (intc_virt + 0x68) -#define INTC_INTENB_0 (intc_virt + 0x70) -#define INTC_INTENB_1 (intc_virt + 0x78) -#define INTC_INTDSB_0 (intc_virt + 0x80) -#define INTC_INTDSB_1 (intc_virt + 0x88) - -#define INTC_ICR_IRLM 0x1 -#define INTC_INTPRI_PREGS 8 /* 8 Priority Registers */ -#define INTC_INTPRI_PPREG 8 /* 8 Priorities per Register */ - - -/* - * Mapper between the vector ordinal and the IRQ number - * passed to kernel/device drivers. - */ -int intc_evt_to_irq[(0xE20/0x20)+1] = { - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x000 - 0x0E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x100 - 0x1E0 */ - 0, 0, 0, 0, 0, 1, 0, 0, /* 0x200 - 0x2E0 */ - 2, 0, 0, 3, 0, 0, 0, -1, /* 0x300 - 0x3E0 */ - 32, 33, 34, 35, 36, 37, 38, -1, /* 0x400 - 0x4E0 */ - -1, -1, -1, 63, -1, -1, -1, -1, /* 0x500 - 0x5E0 */ - -1, -1, 18, 19, 20, 21, 22, -1, /* 0x600 - 0x6E0 */ - 39, 40, 41, 42, -1, -1, -1, -1, /* 0x700 - 0x7E0 */ - 4, 5, 6, 7, -1, -1, -1, -1, /* 0x800 - 0x8E0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0x900 - 0x9E0 */ - 12, 13, 14, 15, 16, 17, -1, -1, /* 0xA00 - 0xAE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xB00 - 0xBE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xC00 - 0xCE0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 0xD00 - 0xDE0 */ - -1, -1 /* 0xE00 - 0xE20 */ -}; - -/* - * Opposite mapper. - */ -static int IRQ_to_vectorN[NR_INTC_IRQS] = { - 0x12, 0x15, 0x18, 0x1B, 0x40, 0x41, 0x42, 0x43, /* 0- 7 */ - -1, -1, -1, -1, 0x50, 0x51, 0x52, 0x53, /* 8-15 */ - 0x54, 0x55, 0x32, 0x33, 0x34, 0x35, 0x36, -1, /* 16-23 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 24-31 */ - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x38, /* 32-39 */ - 0x39, 0x3A, 0x3B, -1, -1, -1, -1, -1, /* 40-47 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* 48-55 */ - -1, -1, -1, -1, -1, -1, -1, 0x2B, /* 56-63 */ - -}; - -static unsigned long intc_virt; - -static unsigned int startup_intc_irq(unsigned int irq); -static void shutdown_intc_irq(unsigned int irq); -static void enable_intc_irq(unsigned int irq); -static void disable_intc_irq(unsigned int irq); -static void mask_and_ack_intc(unsigned int); -static void end_intc_irq(unsigned int irq); - -static struct hw_interrupt_type intc_irq_type = { - .typename = "INTC", - .startup = startup_intc_irq, - .shutdown = shutdown_intc_irq, - .enable = enable_intc_irq, - .disable = disable_intc_irq, - .ack = mask_and_ack_intc, - .end = end_intc_irq -}; - -static int irlm; /* IRL mode */ - -static unsigned int startup_intc_irq(unsigned int irq) -{ - enable_intc_irq(irq); - return 0; /* never anything pending */ -} - -static void shutdown_intc_irq(unsigned int irq) -{ - disable_intc_irq(irq); -} - -static void enable_intc_irq(unsigned int irq) -{ - unsigned long reg; - unsigned long bitmask; - - if ((irq <= IRQ_IRL3) && (irlm == NO_PRIORITY)) - printk("Trying to use straight IRL0-3 with an encoding platform.\n"); - - if (irq < 32) { - reg = INTC_INTENB_0; - bitmask = 1 << irq; - } else { - reg = INTC_INTENB_1; - bitmask = 1 << (irq - 32); - } - - ctrl_outl(bitmask, reg); -} - -static void disable_intc_irq(unsigned int irq) -{ - unsigned long reg; - unsigned long bitmask; - - if (irq < 32) { - reg = INTC_INTDSB_0; - bitmask = 1 << irq; - } else { - reg = INTC_INTDSB_1; - bitmask = 1 << (irq - 32); - } - - ctrl_outl(bitmask, reg); -} - -static void mask_and_ack_intc(unsigned int irq) -{ - disable_intc_irq(irq); -} - -static void end_intc_irq(unsigned int irq) -{ - enable_intc_irq(irq); -} - -/* For future use, if we ever support IRLM=0) */ -void make_intc_irq(unsigned int irq) -{ - disable_irq_nosync(irq); - irq_desc[irq].chip = &intc_irq_type; - disable_intc_irq(irq); -} - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_SYSCTL) -int intc_irq_describe(char* p, int irq) -{ - if (irq < NR_INTC_IRQS) - return sprintf(p, "(0x%3x)", IRQ_to_vectorN[irq]*0x20); - else - return 0; -} -#endif - -void __init init_IRQ(void) -{ - unsigned long long __dummy0, __dummy1=~0x00000000100000f0; - unsigned long reg; - unsigned long data; - int i; - - intc_virt = onchip_remap(INTC_BASE, 1024, "INTC"); - if (!intc_virt) { - panic("Unable to remap INTC\n"); - } - - - /* Set default: per-line enable/disable, priority driven ack/eoi */ - for (i = 0; i < NR_INTC_IRQS; i++) { - if (platform_int_priority[i] != NO_PRIORITY) { - irq_desc[i].chip = &intc_irq_type; - } - } - - - /* Disable all interrupts and set all priorities to 0 to avoid trouble */ - ctrl_outl(-1, INTC_INTDSB_0); - ctrl_outl(-1, INTC_INTDSB_1); - - for (reg = INTC_INTPRI_0, i = 0; i < INTC_INTPRI_PREGS; i++, reg += 8) - ctrl_outl( NO_PRIORITY, reg); - - - /* Set IRLM */ - /* If all the priorities are set to 'no priority', then - * assume we are using encoded mode. - */ - irlm = platform_int_priority[IRQ_IRL0] + platform_int_priority[IRQ_IRL1] + \ - platform_int_priority[IRQ_IRL2] + platform_int_priority[IRQ_IRL3]; - - if (irlm == NO_PRIORITY) { - /* IRLM = 0 */ - reg = INTC_ICR_CLEAR; - i = IRQ_INTA; - printk("Trying to use encoded IRL0-3. IRLs unsupported.\n"); - } else { - /* IRLM = 1 */ - reg = INTC_ICR_SET; - i = IRQ_IRL0; - } - ctrl_outl(INTC_ICR_IRLM, reg); - - /* Set interrupt priorities according to platform description */ - for (data = 0, reg = INTC_INTPRI_0; i < NR_INTC_IRQS; i++) { - data |= platform_int_priority[i] << ((i % INTC_INTPRI_PPREG) * 4); - if ((i % INTC_INTPRI_PPREG) == (INTC_INTPRI_PPREG - 1)) { - /* Upon the 7th, set Priority Register */ - ctrl_outl(data, reg); - data = 0; - reg += 8; - } - } - -#ifdef CONFIG_SH_CAYMAN - { - extern void init_cayman_irq(void); - - init_cayman_irq(); - } -#endif - - /* - * And now let interrupts come in. - * sti() is not enough, we need to - * lower priority, too. - */ - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} diff -puN arch/sh64/kernel/led.c~git-sh /dev/null --- a/arch/sh64/kernel/led.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * arch/sh64/kernel/led.c - * - * Copyright (C) 2002 Stuart Menefy - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Flash the LEDs - */ -#include -#include - -void mach_led(int pos, int val); - -/* acts like an actual heart beat -- ie thump-thump-pause... */ -void heartbeat(void) -{ - static unsigned int cnt = 0, period = 0, dist = 0; - - if (cnt == 0 || cnt == dist) { - mach_led(-1, 1); - } else if (cnt == 7 || cnt == dist + 7) { - mach_led(-1, 0); - } - - if (++cnt > period) { - cnt = 0; - - /* - * The hyperbolic function below modifies the heartbeat period - * length in dependency of the current (5min) load. It goes - * through the points f(0)=126, f(1)=86, f(5)=51, f(inf)->30. - */ - period = ((672 << FSHIFT) / (5 * avenrun[0] + - (7 << FSHIFT))) + 30; - dist = period / 4; - } -} - diff -puN arch/sh64/kernel/module.c~git-sh /dev/null --- a/arch/sh64/kernel/module.c +++ /dev/null @@ -1,161 +0,0 @@ -/* Kernel module help for sh64. - - 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 program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - Copyright 2004 SuperH (UK) Ltd - Author: Richard Curnow - - Based on the sh version, and on code from the sh64-specific parts of - modutils, originally written by Richard Curnow and Ben Gaster. - -*/ -#include -#include -#include -#include -#include -#include - -#if 0 -#define DEBUGP printk -#else -#define DEBUGP(fmt...) -#endif - -void *module_alloc(unsigned long size) -{ - if (size == 0) - return NULL; - return vmalloc(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_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; - Elf32_Sym *sym; - Elf32_Addr relocation; - uint32_t *location; - int align; - int is_shmedia; - - DEBUGP("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { - /* This is where to make the change */ - location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr - + rel[i].r_offset; - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rel[i].r_info); - relocation = sym->st_value + rel[i].r_addend; - align = (int)location & 3; - - /* For text addresses, bit2 of the st_other field indicates - * whether the symbol is SHmedia (1) or SHcompact (0). If - * SHmedia, the LSB of the symbol needs to be asserted - * for the CPU to be in SHmedia mode when it starts executing - * the branch target. */ - is_shmedia = (sym->st_other & 4) ? 1 : 0; - if (is_shmedia) { - relocation |= 1; - } - - switch (ELF32_R_TYPE(rel[i].r_info)) { - case R_SH_DIR32: - DEBUGP("R_SH_DIR32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location += relocation; - break; - case R_SH_REL32: - DEBUGP("R_SH_REL32 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location += relocation; - break; - case R_SH_IMM_LOW16: - DEBUGP("R_SH_IMM_LOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location = (*location & ~0x3fffc00) | - ((relocation & 0xffff) << 10); - break; - case R_SH_IMM_MEDLOW16: - DEBUGP("R_SH_IMM_MEDLOW16 @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - *location = (*location & ~0x3fffc00) | - (((relocation >> 16) & 0xffff) << 10); - break; - case R_SH_IMM_LOW16_PCREL: - DEBUGP("R_SH_IMM_LOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location = (*location & ~0x3fffc00) | - ((relocation & 0xffff) << 10); - break; - case R_SH_IMM_MEDLOW16_PCREL: - DEBUGP("R_SH_IMM_MEDLOW16_PCREL @%08lx = %08lx\n", (unsigned long) location, (unsigned long) relocation); - relocation -= (Elf32_Addr) location; - *location = (*location & ~0x3fffc00) | - (((relocation >> 16) & 0xffff) << 10); - break; - default: - printk(KERN_ERR "module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rel[i].r_info)); - return -ENOEXEC; - } - } - 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: REL 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) -{ -} - diff -puN arch/sh64/kernel/pci_sh5.c~git-sh /dev/null --- a/arch/sh64/kernel/pci_sh5.c +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Support functions for the SH5 PCI hardware. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "pci_sh5.h" - -static unsigned long pcicr_virt; -unsigned long pciio_virt; - -static void __init pci_fixup_ide_bases(struct pci_dev *d) -{ - int i; - - /* - * PCI IDE controllers use non-standard I/O port decoding, respect it. - */ - if ((d->class >> 8) != PCI_CLASS_STORAGE_IDE) - return; - printk("PCI: IDE base address fixup for %s\n", pci_name(d)); - for(i=0; i<4; i++) { - struct resource *r = &d->resource[i]; - if ((r->start & ~0x80) == 0x374) { - r->start |= 2; - r->end = r->start; - } - } -} -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases); - -char * __devinit pcibios_setup(char *str) -{ - return str; -} - -/* Rounds a number UP to the nearest power of two. Used for - * sizing the PCI window. - */ -static u32 __init r2p2(u32 num) -{ - int i = 31; - u32 tmp = num; - - if (num == 0) - return 0; - - do { - if (tmp & (1 << 31)) - break; - i--; - tmp <<= 1; - } while (i >= 0); - - tmp = 1 << i; - /* If the original number isn't a power of 2, round it up */ - if (tmp != num) - tmp <<= 1; - - return tmp; -} - -extern unsigned long long memory_start, memory_end; - -int __init sh5pci_init(unsigned memStart, unsigned memSize) -{ - u32 lsr0; - u32 uval; - - pcicr_virt = onchip_remap(SH5PCI_ICR_BASE, 1024, "PCICR"); - if (!pcicr_virt) { - panic("Unable to remap PCICR\n"); - } - - pciio_virt = onchip_remap(SH5PCI_IO_BASE, 0x10000, "PCIIO"); - if (!pciio_virt) { - panic("Unable to remap PCIIO\n"); - } - - pr_debug("Register base addres is 0x%08lx\n", pcicr_virt); - - /* Clear snoop registers */ - SH5PCI_WRITE(CSCR0, 0); - SH5PCI_WRITE(CSCR1, 0); - - pr_debug("Wrote to reg\n"); - - /* Switch off interrupts */ - SH5PCI_WRITE(INTM, 0); - SH5PCI_WRITE(AINTM, 0); - SH5PCI_WRITE(PINTM, 0); - - /* Set bus active, take it out of reset */ - uval = SH5PCI_READ(CR); - - /* Set command Register */ - SH5PCI_WRITE(CR, uval | CR_LOCK_MASK | CR_CFINT| CR_FTO | CR_PFE | CR_PFCS | CR_BMAM); - - uval=SH5PCI_READ(CR); - pr_debug("CR is actually 0x%08x\n",uval); - - /* Allow it to be a master */ - /* NB - WE DISABLE I/O ACCESS to stop overlap */ - /* set WAIT bit to enable stepping, an attempt to improve stability */ - SH5PCI_WRITE_SHORT(CSR_CMD, - PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_WAIT); - - /* - ** Set translation mapping memory in order to convert the address - ** used for the main bus, to the PCI internal address. - */ - SH5PCI_WRITE(MBR,0x40000000); - - /* Always set the max size 512M */ - SH5PCI_WRITE(MBMR, PCISH5_MEM_SIZCONV(512*1024*1024)); - - /* - ** I/O addresses are mapped at internal PCI specific address - ** as is described into the configuration bridge table. - ** These are changed to 0, to allow cards that have legacy - ** io such as vga to function correctly. We set the SH5 IOBAR to - ** 256K, which is a bit big as we can only have 64K of address space - */ - - SH5PCI_WRITE(IOBR,0x0); - - pr_debug("PCI:Writing 0x%08x to IOBR\n",0); - - /* Set up a 256K window. Totally pointless waste of address space */ - SH5PCI_WRITE(IOBMR,0); - pr_debug("PCI:Writing 0x%08x to IOBMR\n",0); - - /* The SH5 has a HUGE 256K I/O region, which breaks the PCI spec. Ideally, - * we would want to map the I/O region somewhere, but it is so big this is not - * that easy! - */ - SH5PCI_WRITE(CSR_IBAR0,~0); - /* Set memory size value */ - memSize = memory_end - memory_start; - - /* Now we set up the mbars so the PCI bus can see the memory of the machine */ - if (memSize < (1024 * 1024)) { - printk(KERN_ERR "PCISH5: Ridiculous memory size of 0x%x?\n", memSize); - return -EINVAL; - } - - /* Set LSR 0 */ - lsr0 = (memSize > (512 * 1024 * 1024)) ? 0x1ff00001 : ((r2p2(memSize) - 0x100000) | 0x1); - SH5PCI_WRITE(LSR0, lsr0); - - pr_debug("PCI:Writing 0x%08x to LSR0\n",lsr0); - - /* Set MBAR 0 */ - SH5PCI_WRITE(CSR_MBAR0, memory_start); - SH5PCI_WRITE(LAR0, memory_start); - - SH5PCI_WRITE(CSR_MBAR1,0); - SH5PCI_WRITE(LAR1,0); - SH5PCI_WRITE(LSR1,0); - - pr_debug("PCI:Writing 0x%08llx to CSR_MBAR0\n",memory_start); - pr_debug("PCI:Writing 0x%08llx to LAR0\n",memory_start); - - /* Enable the PCI interrupts on the device */ - SH5PCI_WRITE(INTM, ~0); - SH5PCI_WRITE(AINTM, ~0); - SH5PCI_WRITE(PINTM, ~0); - - pr_debug("Switching on all error interrupts\n"); - - return(0); -} - -static int sh5pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 *val) -{ - SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - *val = (u8)SH5PCI_READ_BYTE(PDR + (where & 3)); - break; - case 2: - *val = (u16)SH5PCI_READ_SHORT(PDR + (where & 2)); - break; - case 4: - *val = SH5PCI_READ(PDR); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static int sh5pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - SH5PCI_WRITE(PAR, CONFIG_CMD(bus, devfn, where)); - - switch (size) { - case 1: - SH5PCI_WRITE_BYTE(PDR + (where & 3), (u8)val); - break; - case 2: - SH5PCI_WRITE_SHORT(PDR + (where & 2), (u16)val); - break; - case 4: - SH5PCI_WRITE(PDR, val); - break; - } - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops pci_config_ops = { - .read = sh5pci_read, - .write = sh5pci_write, -}; - -/* Everything hangs off this */ -static struct pci_bus *pci_root_bus; - - -static u8 __init no_swizzle(struct pci_dev *dev, u8 * pin) -{ - pr_debug("swizzle for dev %d on bus %d slot %d pin is %d\n", - dev->devfn,dev->bus->number, PCI_SLOT(dev->devfn),*pin); - return PCI_SLOT(dev->devfn); -} - -static inline u8 bridge_swizzle(u8 pin, u8 slot) -{ - return (((pin-1) + slot) % 4) + 1; -} - -u8 __init common_swizzle(struct pci_dev *dev, u8 *pinp) -{ - if (dev->bus->number != 0) { - u8 pin = *pinp; - do { - pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn)); - /* Move up the chain of bridges. */ - dev = dev->bus->self; - } while (dev->bus->self); - *pinp = pin; - - /* The slot is the slot of the last bridge. */ - } - - return PCI_SLOT(dev->devfn); -} - -/* This needs to be shunted out of here into the board specific bit */ - -static int __init map_cayman_irq(struct pci_dev *dev, u8 slot, u8 pin) -{ - int result = -1; - - /* The complication here is that the PCI IRQ lines from the Cayman's 2 - 5V slots get into the CPU via a different path from the IRQ lines - from the 3 3.3V slots. Thus, we have to detect whether the card's - interrupts go via the 5V or 3.3V path, i.e. the 'bridge swizzling' - at the point where we cross from 5V to 3.3V is not the normal case. - - The added complication is that we don't know that the 5V slots are - always bus 2, because a card containing a PCI-PCI bridge may be - plugged into a 3.3V slot, and this changes the bus numbering. - - Also, the Cayman has an intermediate PCI bus that goes a custom - expansion board header (and to the secondary bridge). This bus has - never been used in practice. - - The 1ary onboard PCI-PCI bridge is device 3 on bus 0 - The 2ary onboard PCI-PCI bridge is device 0 on the 2ary bus of the 1ary bridge. - */ - - struct slot_pin { - int slot; - int pin; - } path[4]; - int i=0; - - while (dev->bus->number > 0) { - - slot = path[i].slot = PCI_SLOT(dev->devfn); - pin = path[i].pin = bridge_swizzle(pin, slot); - dev = dev->bus->self; - i++; - if (i > 3) panic("PCI path to root bus too long!\n"); - } - - slot = PCI_SLOT(dev->devfn); - /* This is the slot on bus 0 through which the device is eventually - reachable. */ - - /* Now work back up. */ - if ((slot < 3) || (i == 0)) { - /* Bus 0 (incl. PCI-PCI bridge itself) : perform the final - swizzle now. */ - result = IRQ_INTA + bridge_swizzle(pin, slot) - 1; - } else { - i--; - slot = path[i].slot; - pin = path[i].pin; - if (slot > 0) { - panic("PCI expansion bus device found - not handled!\n"); - } else { - if (i > 0) { - /* 5V slots */ - i--; - slot = path[i].slot; - pin = path[i].pin; - /* 'pin' was swizzled earlier wrt slot, don't do it again. */ - result = IRQ_P2INTA + (pin - 1); - } else { - /* IRQ for 2ary PCI-PCI bridge : unused */ - result = -1; - } - } - } - - return result; -} - -static irqreturn_t pcish5_err_irq(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - unsigned pci_int, pci_air, pci_cir, pci_aint; - - pci_int = SH5PCI_READ(INT); - pci_cir = SH5PCI_READ(CIR); - pci_air = SH5PCI_READ(AIR); - - if (pci_int) { - printk("PCI INTERRUPT (at %08llx)!\n", regs->pc); - printk("PCI INT -> 0x%x\n", pci_int & 0xffff); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - SH5PCI_WRITE(INT, ~0); - } - - pci_aint = SH5PCI_READ(AINT); - if (pci_aint) { - printk("PCI ARB INTERRUPT!\n"); - printk("PCI AINT -> 0x%x\n", pci_aint); - printk("PCI AIR -> 0x%x\n", pci_air); - printk("PCI CIR -> 0x%x\n", pci_cir); - SH5PCI_WRITE(AINT, ~0); - } - - return IRQ_HANDLED; -} - -static irqreturn_t pcish5_serr_irq(int irq, void *dev_id) -{ - printk("SERR IRQ\n"); - - return IRQ_NONE; -} - -static void __init -pcibios_size_bridge(struct pci_bus *bus, struct resource *ior, - struct resource *memr) -{ - struct resource io_res, mem_res; - struct pci_dev *dev; - struct pci_dev *bridge = bus->self; - struct list_head *ln; - - if (!bridge) - return; /* host bridge, nothing to do */ - - /* set reasonable default locations for pcibios_align_resource */ - io_res.start = PCIBIOS_MIN_IO; - mem_res.start = PCIBIOS_MIN_MEM; - - io_res.end = io_res.start; - mem_res.end = mem_res.start; - - /* Collect information about how our direct children are layed out. */ - for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) { - int i; - dev = pci_dev_b(ln); - - /* Skip bridges for now */ - if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI) - continue; - - for (i = 0; i < PCI_NUM_RESOURCES; i++) { - struct resource res; - unsigned long size; - - memcpy(&res, &dev->resource[i], sizeof(res)); - size = res.end - res.start + 1; - - if (res.flags & IORESOURCE_IO) { - res.start = io_res.end; - pcibios_align_resource(dev, &res, size, 0); - io_res.end = res.start + size; - } else if (res.flags & IORESOURCE_MEM) { - res.start = mem_res.end; - pcibios_align_resource(dev, &res, size, 0); - mem_res.end = res.start + size; - } - } - } - - /* And for all of the subordinate busses. */ - for (ln=bus->children.next; ln != &bus->children; ln=ln->next) - pcibios_size_bridge(pci_bus_b(ln), &io_res, &mem_res); - - /* turn the ending locations into sizes (subtract start) */ - io_res.end -= io_res.start; - mem_res.end -= mem_res.start; - - /* Align the sizes up by bridge rules */ - io_res.end = ALIGN(io_res.end, 4*1024) - 1; - mem_res.end = ALIGN(mem_res.end, 1*1024*1024) - 1; - - /* Adjust the bridge's allocation requirements */ - bridge->resource[0].end = bridge->resource[0].start + io_res.end; - bridge->resource[1].end = bridge->resource[1].start + mem_res.end; - - bridge->resource[PCI_BRIDGE_RESOURCES].end = - bridge->resource[PCI_BRIDGE_RESOURCES].start + io_res.end; - bridge->resource[PCI_BRIDGE_RESOURCES+1].end = - bridge->resource[PCI_BRIDGE_RESOURCES+1].start + mem_res.end; - - /* adjust parent's resource requirements */ - if (ior) { - ior->end = ALIGN(ior->end, 4*1024); - ior->end += io_res.end; - } - - if (memr) { - memr->end = ALIGN(memr->end, 1*1024*1024); - memr->end += mem_res.end; - } -} - -static void __init pcibios_size_bridges(void) -{ - struct resource io_res, mem_res; - - memset(&io_res, 0, sizeof(io_res)); - memset(&mem_res, 0, sizeof(mem_res)); - - pcibios_size_bridge(pci_root_bus, &io_res, &mem_res); -} - -static int __init pcibios_init(void) -{ - if (request_irq(IRQ_ERR, pcish5_err_irq, - IRQF_DISABLED, "PCI Error",NULL) < 0) { - printk(KERN_ERR "PCISH5: Cannot hook PCI_PERR interrupt\n"); - return -EINVAL; - } - - if (request_irq(IRQ_SERR, pcish5_serr_irq, - IRQF_DISABLED, "PCI SERR interrupt", NULL) < 0) { - printk(KERN_ERR "PCISH5: Cannot hook PCI_SERR interrupt\n"); - return -EINVAL; - } - - /* The pci subsystem needs to know where memory is and how much - * of it there is. I've simply made these globals. A better mechanism - * is probably needed. - */ - sh5pci_init(__pa(memory_start), - __pa(memory_end) - __pa(memory_start)); - - pci_root_bus = pci_scan_bus(0, &pci_config_ops, NULL); - pcibios_size_bridges(); - pci_assign_unassigned_resources(); - pci_fixup_irqs(no_swizzle, map_cayman_irq); - - return 0; -} - -subsys_initcall(pcibios_init); - -void __devinit pcibios_fixup_bus(struct pci_bus *bus) -{ - struct pci_dev *dev = bus->self; - int i; - -#if 1 - if(dev) { - for(i=0; i<3; i++) { - bus->resource[i] = - &dev->resource[PCI_BRIDGE_RESOURCES+i]; - bus->resource[i]->name = bus->name; - } - bus->resource[0]->flags |= IORESOURCE_IO; - bus->resource[1]->flags |= IORESOURCE_MEM; - - /* For now, propagate host limits to the bus; - * we'll adjust them later. */ - -#if 1 - bus->resource[0]->end = 64*1024 - 1 ; - bus->resource[1]->end = PCIBIOS_MIN_MEM+(256*1024*1024)-1; - bus->resource[0]->start = PCIBIOS_MIN_IO; - bus->resource[1]->start = PCIBIOS_MIN_MEM; -#else - bus->resource[0]->end = 0; - bus->resource[1]->end = 0; - bus->resource[0]->start =0; - bus->resource[1]->start = 0; -#endif - /* Turn off downstream PF memory address range by default */ - bus->resource[2]->start = 1024*1024; - bus->resource[2]->end = bus->resource[2]->start - 1; - } -#endif - -} - diff -puN arch/sh64/kernel/pci_sh5.h~git-sh /dev/null --- a/arch/sh64/kernel/pci_sh5.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Definitions for the SH5 PCI hardware. - */ - -/* Product ID */ -#define PCISH5_PID 0x350d - -/* vendor ID */ -#define PCISH5_VID 0x1054 - -/* Configuration types */ -#define ST_TYPE0 0x00 /* Configuration cycle type 0 */ -#define ST_TYPE1 0x01 /* Configuration cycle type 1 */ - -/* VCR data */ -#define PCISH5_VCR_STATUS 0x00 -#define PCISH5_VCR_VERSION 0x08 - -/* -** ICR register offsets and bits -*/ -#define PCISH5_ICR_CR 0x100 /* PCI control register values */ -#define CR_PBAM (1<<12) -#define CR_PFCS (1<<11) -#define CR_FTO (1<<10) -#define CR_PFE (1<<9) -#define CR_TBS (1<<8) -#define CR_SPUE (1<<7) -#define CR_BMAM (1<<6) -#define CR_HOST (1<<5) -#define CR_CLKEN (1<<4) -#define CR_SOCS (1<<3) -#define CR_IOCS (1<<2) -#define CR_RSTCTL (1<<1) -#define CR_CFINT (1<<0) -#define CR_LOCK_MASK 0xa5000000 - -#define PCISH5_ICR_INT 0x114 /* Interrupt registert values */ -#define INT_MADIM (1<<2) - -#define PCISH5_ICR_LSR0 0X104 /* Local space register values */ -#define PCISH5_ICR_LSR1 0X108 /* Local space register values */ -#define PCISH5_ICR_LAR0 0x10c /* Local address register values */ -#define PCISH5_ICR_LAR1 0x110 /* Local address register values */ -#define PCISH5_ICR_INTM 0x118 /* Interrupt mask register values */ -#define PCISH5_ICR_AIR 0x11c /* Interrupt error address information register values */ -#define PCISH5_ICR_CIR 0x120 /* Interrupt error command information register values */ -#define PCISH5_ICR_AINT 0x130 /* Interrupt error arbiter interrupt register values */ -#define PCISH5_ICR_AINTM 0x134 /* Interrupt error arbiter interrupt mask register values */ -#define PCISH5_ICR_BMIR 0x138 /* Interrupt error info register of bus master values */ -#define PCISH5_ICR_PAR 0x1c0 /* Pio address register values */ -#define PCISH5_ICR_MBR 0x1c4 /* Memory space bank register values */ -#define PCISH5_ICR_IOBR 0x1c8 /* I/O space bank register values */ -#define PCISH5_ICR_PINT 0x1cc /* power management interrupt register values */ -#define PCISH5_ICR_PINTM 0x1d0 /* power management interrupt mask register values */ -#define PCISH5_ICR_MBMR 0x1d8 /* memory space bank mask register values */ -#define PCISH5_ICR_IOBMR 0x1dc /* I/O space bank mask register values */ -#define PCISH5_ICR_CSCR0 0x210 /* PCI cache snoop control register 0 */ -#define PCISH5_ICR_CSCR1 0x214 /* PCI cache snoop control register 1 */ -#define PCISH5_ICR_PDR 0x220 /* Pio data register values */ - -/* These are configs space registers */ -#define PCISH5_ICR_CSR_VID 0x000 /* Vendor id */ -#define PCISH5_ICR_CSR_DID 0x002 /* Device id */ -#define PCISH5_ICR_CSR_CMD 0x004 /* Command register */ -#define PCISH5_ICR_CSR_STATUS 0x006 /* Stautus */ -#define PCISH5_ICR_CSR_IBAR0 0x010 /* I/O base address register */ -#define PCISH5_ICR_CSR_MBAR0 0x014 /* First Memory base address register */ -#define PCISH5_ICR_CSR_MBAR1 0x018 /* Second Memory base address register */ - - - -/* Base address of registers */ -#define SH5PCI_ICR_BASE (PHYS_PCI_BLOCK + 0x00040000) -#define SH5PCI_IO_BASE (PHYS_PCI_BLOCK + 0x00800000) -/* #define SH5PCI_VCR_BASE (P2SEG_PCICB_BLOCK + P2SEG) */ - -/* Register selection macro */ -#define PCISH5_ICR_REG(x) ( pcicr_virt + (PCISH5_ICR_##x)) -/* #define PCISH5_VCR_REG(x) ( SH5PCI_VCR_BASE (PCISH5_VCR_##x)) */ - -/* Write I/O functions */ -#define SH5PCI_WRITE(reg,val) ctrl_outl((u32)(val),PCISH5_ICR_REG(reg)) -#define SH5PCI_WRITE_SHORT(reg,val) ctrl_outw((u16)(val),PCISH5_ICR_REG(reg)) -#define SH5PCI_WRITE_BYTE(reg,val) ctrl_outb((u8)(val),PCISH5_ICR_REG(reg)) - -/* Read I/O functions */ -#define SH5PCI_READ(reg) ctrl_inl(PCISH5_ICR_REG(reg)) -#define SH5PCI_READ_SHORT(reg) ctrl_inw(PCISH5_ICR_REG(reg)) -#define SH5PCI_READ_BYTE(reg) ctrl_inb(PCISH5_ICR_REG(reg)) - -/* Set PCI config bits */ -#define SET_CONFIG_BITS(bus,devfn,where) ((((bus) << 16) | ((devfn) << 8) | ((where) & ~3)) | 0x80000000) - -/* Set PCI command register */ -#define CONFIG_CMD(bus, devfn, where) SET_CONFIG_BITS(bus->number,devfn,where) - -/* Size converters */ -#define PCISH5_MEM_SIZCONV(x) (((x / 0x40000) - 1) << 18) -#define PCISH5_IO_SIZCONV(x) (((x / 0x40000) - 1) << 18) - - diff -puN arch/sh64/kernel/pcibios.c~git-sh /dev/null --- a/arch/sh64/kernel/pcibios.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * $Id: pcibios.c,v 1.1 2001/08/24 12:38:19 dwmw2 Exp $ - * - * arch/sh/kernel/pcibios.c - * - * Copyright (C) 2002 STMicroelectronics Limited - * Author : David J. McKay - * - * Copyright (C) 2004 Richard Curnow, SuperH UK Limited - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * This is GPL'd. - * - * Provided here are generic versions of: - * pcibios_update_resource() - * pcibios_align_resource() - * pcibios_enable_device() - * pcibios_set_master() - * pcibios_update_irq() - * - * These functions are collected here to reduce duplication of common - * code amongst the many platform-specific PCI support code files. - * - * Platform-specific files are expected to provide: - * pcibios_fixup_bus() - * pcibios_init() - * pcibios_setup() - * pcibios_fixup_pbus_ranges() - */ - -#include -#include -#include - -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); - } -} - -/* - * We need to avoid collisions with `mirrored' VGA ports - * and other strange ISA hardware, so we always want the - * addresses to be allocated in the 0x000-0x0ff region - * modulo 0x400. - */ -void pcibios_align_resource(void *data, struct resource *res, - resource_size_t size, resource_size_t align) -{ - if (res->flags & IORESOURCE_IO) { - resource_size_t start = res->start; - - if (start & 0x300) { - start = (start + 0x3ff) & ~0x3ff; - res->start = start; - } - } -} - -static void pcibios_enable_bridge(struct pci_dev *dev) -{ - struct pci_bus *bus = dev->subordinate; - u16 cmd, old_cmd; - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - - if (bus->resource[0]->flags & IORESOURCE_IO) { - cmd |= PCI_COMMAND_IO; - } - if ((bus->resource[1]->flags & IORESOURCE_MEM) || - (bus->resource[2]->flags & IORESOURCE_PREFETCH)) { - cmd |= PCI_COMMAND_MEMORY; - } - - if (cmd != old_cmd) { - pci_write_config_word(dev, PCI_COMMAND, cmd); - } - - printk("PCI bridge %s, command register -> %04x\n", - pci_name(dev), cmd); - -} - - - -int pcibios_enable_device(struct pci_dev *dev, int mask) -{ - u16 cmd, old_cmd; - int idx; - struct resource *r; - - if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) { - pcibios_enable_bridge(dev); - } - - pci_read_config_word(dev, PCI_COMMAND, &cmd); - old_cmd = cmd; - for(idx=0; idx<6; idx++) { - 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(KERN_INFO "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 and set - * the latency timer as it may not be properly set. - */ -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_INFO "PCI: Setting latency timer of device %s to %d\n", pci_name(dev), lat); - pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat); -} - -void __init pcibios_update_irq(struct pci_dev *dev, int irq) -{ - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); -} diff -puN arch/sh64/kernel/process.c~git-sh /dev/null --- a/arch/sh64/kernel/process.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/process.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - * Started from SH3/4 version: - * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima - * - * In turn started from i386 version: - * Copyright (C) 1995 Linus Torvalds - * - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct task_struct *last_task_used_math = NULL; - -static int hlt_counter = 1; - -#define HARD_IDLE_TIMEOUT (HZ / 3) - -void disable_hlt(void) -{ - hlt_counter++; -} - -void enable_hlt(void) -{ - hlt_counter--; -} - -static int __init nohlt_setup(char *__unused) -{ - hlt_counter = 1; - return 1; -} - -static int __init hlt_setup(char *__unused) -{ - hlt_counter = 0; - return 1; -} - -__setup("nohlt", nohlt_setup); -__setup("hlt", hlt_setup); - -static inline void hlt(void) -{ - __asm__ __volatile__ ("sleep" : : : "memory"); -} - -/* - * The idle loop on a uniprocessor SH.. - */ -void cpu_idle(void) -{ - /* endless idle loop with no priority at all */ - while (1) { - if (hlt_counter) { - while (!need_resched()) - cpu_relax(); - } else { - local_irq_disable(); - while (!need_resched()) { - local_irq_enable(); - hlt(); - local_irq_disable(); - } - local_irq_enable(); - } - preempt_enable_no_resched(); - schedule(); - preempt_disable(); - } - -} - -void machine_restart(char * __unused) -{ - extern void phys_stext(void); - - phys_stext(); -} - -void machine_halt(void) -{ - for (;;); -} - -void machine_power_off(void) -{ - extern void enter_deep_standby(void); - - enter_deep_standby(); -} - -void (*pm_power_off)(void) = machine_power_off; -EXPORT_SYMBOL(pm_power_off); - -void show_regs(struct pt_regs * regs) -{ - unsigned long long ah, al, bh, bl, ch, cl; - - printk("\n"); - - ah = (regs->pc) >> 32; - al = (regs->pc) & 0xffffffff; - bh = (regs->regs[18]) >> 32; - bl = (regs->regs[18]) & 0xffffffff; - ch = (regs->regs[15]) >> 32; - cl = (regs->regs[15]) & 0xffffffff; - printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->sr) >> 32; - al = (regs->sr) & 0xffffffff; - asm volatile ("getcon " __TEA ", %0" : "=r" (bh)); - asm volatile ("getcon " __TEA ", %0" : "=r" (bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __KCR0 ", %0" : "=r" (ch)); - asm volatile ("getcon " __KCR0 ", %0" : "=r" (cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[0]) >> 32; - al = (regs->regs[0]) & 0xffffffff; - bh = (regs->regs[1]) >> 32; - bl = (regs->regs[1]) & 0xffffffff; - ch = (regs->regs[2]) >> 32; - cl = (regs->regs[2]) & 0xffffffff; - printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[3]) >> 32; - al = (regs->regs[3]) & 0xffffffff; - bh = (regs->regs[4]) >> 32; - bl = (regs->regs[4]) & 0xffffffff; - ch = (regs->regs[5]) >> 32; - cl = (regs->regs[5]) & 0xffffffff; - printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[6]) >> 32; - al = (regs->regs[6]) & 0xffffffff; - bh = (regs->regs[7]) >> 32; - bl = (regs->regs[7]) & 0xffffffff; - ch = (regs->regs[8]) >> 32; - cl = (regs->regs[8]) & 0xffffffff; - printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[9]) >> 32; - al = (regs->regs[9]) & 0xffffffff; - bh = (regs->regs[10]) >> 32; - bl = (regs->regs[10]) & 0xffffffff; - ch = (regs->regs[11]) >> 32; - cl = (regs->regs[11]) & 0xffffffff; - printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[12]) >> 32; - al = (regs->regs[12]) & 0xffffffff; - bh = (regs->regs[13]) >> 32; - bl = (regs->regs[13]) & 0xffffffff; - ch = (regs->regs[14]) >> 32; - cl = (regs->regs[14]) & 0xffffffff; - printk("R12 : %08Lx%08Lx R13 : %08Lx%08Lx R14 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[16]) >> 32; - al = (regs->regs[16]) & 0xffffffff; - bh = (regs->regs[17]) >> 32; - bl = (regs->regs[17]) & 0xffffffff; - ch = (regs->regs[19]) >> 32; - cl = (regs->regs[19]) & 0xffffffff; - printk("R16 : %08Lx%08Lx R17 : %08Lx%08Lx R19 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[20]) >> 32; - al = (regs->regs[20]) & 0xffffffff; - bh = (regs->regs[21]) >> 32; - bl = (regs->regs[21]) & 0xffffffff; - ch = (regs->regs[22]) >> 32; - cl = (regs->regs[22]) & 0xffffffff; - printk("R20 : %08Lx%08Lx R21 : %08Lx%08Lx R22 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[23]) >> 32; - al = (regs->regs[23]) & 0xffffffff; - bh = (regs->regs[24]) >> 32; - bl = (regs->regs[24]) & 0xffffffff; - ch = (regs->regs[25]) >> 32; - cl = (regs->regs[25]) & 0xffffffff; - printk("R23 : %08Lx%08Lx R24 : %08Lx%08Lx R25 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[26]) >> 32; - al = (regs->regs[26]) & 0xffffffff; - bh = (regs->regs[27]) >> 32; - bl = (regs->regs[27]) & 0xffffffff; - ch = (regs->regs[28]) >> 32; - cl = (regs->regs[28]) & 0xffffffff; - printk("R26 : %08Lx%08Lx R27 : %08Lx%08Lx R28 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[29]) >> 32; - al = (regs->regs[29]) & 0xffffffff; - bh = (regs->regs[30]) >> 32; - bl = (regs->regs[30]) & 0xffffffff; - ch = (regs->regs[31]) >> 32; - cl = (regs->regs[31]) & 0xffffffff; - printk("R29 : %08Lx%08Lx R30 : %08Lx%08Lx R31 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[32]) >> 32; - al = (regs->regs[32]) & 0xffffffff; - bh = (regs->regs[33]) >> 32; - bl = (regs->regs[33]) & 0xffffffff; - ch = (regs->regs[34]) >> 32; - cl = (regs->regs[34]) & 0xffffffff; - printk("R32 : %08Lx%08Lx R33 : %08Lx%08Lx R34 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[35]) >> 32; - al = (regs->regs[35]) & 0xffffffff; - bh = (regs->regs[36]) >> 32; - bl = (regs->regs[36]) & 0xffffffff; - ch = (regs->regs[37]) >> 32; - cl = (regs->regs[37]) & 0xffffffff; - printk("R35 : %08Lx%08Lx R36 : %08Lx%08Lx R37 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[38]) >> 32; - al = (regs->regs[38]) & 0xffffffff; - bh = (regs->regs[39]) >> 32; - bl = (regs->regs[39]) & 0xffffffff; - ch = (regs->regs[40]) >> 32; - cl = (regs->regs[40]) & 0xffffffff; - printk("R38 : %08Lx%08Lx R39 : %08Lx%08Lx R40 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[41]) >> 32; - al = (regs->regs[41]) & 0xffffffff; - bh = (regs->regs[42]) >> 32; - bl = (regs->regs[42]) & 0xffffffff; - ch = (regs->regs[43]) >> 32; - cl = (regs->regs[43]) & 0xffffffff; - printk("R41 : %08Lx%08Lx R42 : %08Lx%08Lx R43 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[44]) >> 32; - al = (regs->regs[44]) & 0xffffffff; - bh = (regs->regs[45]) >> 32; - bl = (regs->regs[45]) & 0xffffffff; - ch = (regs->regs[46]) >> 32; - cl = (regs->regs[46]) & 0xffffffff; - printk("R44 : %08Lx%08Lx R45 : %08Lx%08Lx R46 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[47]) >> 32; - al = (regs->regs[47]) & 0xffffffff; - bh = (regs->regs[48]) >> 32; - bl = (regs->regs[48]) & 0xffffffff; - ch = (regs->regs[49]) >> 32; - cl = (regs->regs[49]) & 0xffffffff; - printk("R47 : %08Lx%08Lx R48 : %08Lx%08Lx R49 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[50]) >> 32; - al = (regs->regs[50]) & 0xffffffff; - bh = (regs->regs[51]) >> 32; - bl = (regs->regs[51]) & 0xffffffff; - ch = (regs->regs[52]) >> 32; - cl = (regs->regs[52]) & 0xffffffff; - printk("R50 : %08Lx%08Lx R51 : %08Lx%08Lx R52 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[53]) >> 32; - al = (regs->regs[53]) & 0xffffffff; - bh = (regs->regs[54]) >> 32; - bl = (regs->regs[54]) & 0xffffffff; - ch = (regs->regs[55]) >> 32; - cl = (regs->regs[55]) & 0xffffffff; - printk("R53 : %08Lx%08Lx R54 : %08Lx%08Lx R55 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[56]) >> 32; - al = (regs->regs[56]) & 0xffffffff; - bh = (regs->regs[57]) >> 32; - bl = (regs->regs[57]) & 0xffffffff; - ch = (regs->regs[58]) >> 32; - cl = (regs->regs[58]) & 0xffffffff; - printk("R56 : %08Lx%08Lx R57 : %08Lx%08Lx R58 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[59]) >> 32; - al = (regs->regs[59]) & 0xffffffff; - bh = (regs->regs[60]) >> 32; - bl = (regs->regs[60]) & 0xffffffff; - ch = (regs->regs[61]) >> 32; - cl = (regs->regs[61]) & 0xffffffff; - printk("R59 : %08Lx%08Lx R60 : %08Lx%08Lx R61 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[62]) >> 32; - al = (regs->regs[62]) & 0xffffffff; - bh = (regs->tregs[0]) >> 32; - bl = (regs->tregs[0]) & 0xffffffff; - ch = (regs->tregs[1]) >> 32; - cl = (regs->tregs[1]) & 0xffffffff; - printk("R62 : %08Lx%08Lx T0 : %08Lx%08Lx T1 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->tregs[2]) >> 32; - al = (regs->tregs[2]) & 0xffffffff; - bh = (regs->tregs[3]) >> 32; - bl = (regs->tregs[3]) & 0xffffffff; - ch = (regs->tregs[4]) >> 32; - cl = (regs->tregs[4]) & 0xffffffff; - printk("T2 : %08Lx%08Lx T3 : %08Lx%08Lx T4 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->tregs[5]) >> 32; - al = (regs->tregs[5]) & 0xffffffff; - bh = (regs->tregs[6]) >> 32; - bl = (regs->tregs[6]) & 0xffffffff; - ch = (regs->tregs[7]) >> 32; - cl = (regs->tregs[7]) & 0xffffffff; - printk("T5 : %08Lx%08Lx T6 : %08Lx%08Lx T7 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - /* - * If we're in kernel mode, dump the stack too.. - */ - if (!user_mode(regs)) { - void show_stack(struct task_struct *tsk, unsigned long *sp); - unsigned long sp = regs->regs[15] & 0xffffffff; - struct task_struct *tsk = get_current(); - - tsk->thread.kregs = regs; - - show_stack(tsk, (unsigned long *)sp); - } -} - -struct task_struct * alloc_task_struct(void) -{ - /* Get task descriptor pages */ - return (struct task_struct *) - __get_free_pages(GFP_KERNEL, get_order(THREAD_SIZE)); -} - -void free_task_struct(struct task_struct *p) -{ - free_pages((unsigned long) p, get_order(THREAD_SIZE)); -} - -/* - * Create a kernel thread - */ -ATTRIB_NORET void kernel_thread_helper(void *arg, int (*fn)(void *)) -{ - do_exit(fn(arg)); -} - -/* - * This is the mechanism for creating a new kernel thread. - * - * NOTE! Only a kernel-only process(ie the swapper or direct descendants - * who haven't done an "execve()") should use this: it will work within - * a system call from a "real" process, but the process memory space will - * not be freed until both the parent and the child have exited. - */ -int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) -{ - struct pt_regs regs; - - memset(®s, 0, sizeof(regs)); - regs.regs[2] = (unsigned long)arg; - regs.regs[3] = (unsigned long)fn; - - regs.pc = (unsigned long)kernel_thread_helper; - regs.sr = (1 << 30); - - return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, - ®s, 0, NULL, NULL); -} - -/* - * Free current thread data structures etc.. - */ -void exit_thread(void) -{ - /* See arch/sparc/kernel/process.c for the precedent for doing this -- RPC. - - The SH-5 FPU save/restore approach relies on last_task_used_math - pointing to a live task_struct. When another task tries to use the - FPU for the 1st time, the FPUDIS trap handling (see - arch/sh64/kernel/fpu.c) will save the existing FPU state to the - FP regs field within last_task_used_math before re-loading the new - task's FPU state (or initialising it if the FPU has been used - before). So if last_task_used_math is stale, and its page has already been - re-allocated for another use, the consequences are rather grim. Unless we - null it here, there is no other path through which it would get safely - nulled. */ - -#ifdef CONFIG_SH_FPU - if (last_task_used_math == current) { - last_task_used_math = NULL; - } -#endif -} - -void flush_thread(void) -{ - - /* Called by fs/exec.c (flush_old_exec) to remove traces of a - * previously running executable. */ -#ifdef CONFIG_SH_FPU - if (last_task_used_math == current) { - last_task_used_math = NULL; - } - /* Force FPU state to be reinitialised after exec */ - clear_used_math(); -#endif - - /* if we are a kernel thread, about to change to user thread, - * update kreg - */ - if(current->thread.kregs==&fake_swapper_regs) { - current->thread.kregs = - ((struct pt_regs *)(THREAD_SIZE + (unsigned long) current) - 1); - current->thread.uregs = current->thread.kregs; - } -} - -void release_thread(struct task_struct *dead_task) -{ - /* do nothing */ -} - -/* Fill in the fpu structure for a core dump.. */ -int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) -{ -#ifdef CONFIG_SH_FPU - int fpvalid; - struct task_struct *tsk = current; - - fpvalid = !!tsk_used_math(tsk); - if (fpvalid) { - if (current == last_task_used_math) { - grab_fpu(); - fpsave(&tsk->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); - } - - return fpvalid; -#else - return 0; /* Task didn't use the fpu at all. */ -#endif -} - -asmlinkage void ret_from_fork(void); - -int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct pt_regs *childregs; - unsigned long long se; /* Sign extension */ - -#ifdef CONFIG_SH_FPU - if(last_task_used_math == current) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } -#endif - /* Copy from sh version */ - childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1; - - *childregs = *regs; - - if (user_mode(regs)) { - childregs->regs[15] = usp; - p->thread.uregs = childregs; - } else { - childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; - } - - childregs->regs[9] = 0; /* Set return value for child */ - childregs->sr |= SR_FD; /* Invalidate FPU flag */ - - p->thread.sp = (unsigned long) childregs; - p->thread.pc = (unsigned long) ret_from_fork; - - /* - * Sign extend the edited stack. - * Note that thread.pc and thread.pc will stay - * 32-bit wide and context switch must take care - * of NEFF sign extension. - */ - - se = childregs->regs[15]; - se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se; - childregs->regs[15] = se; - - return 0; -} - -asmlinkage int sys_fork(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - return do_fork(SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); -} - -asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - if (!newsp) - newsp = pregs->regs[15]; - return do_fork(clone_flags, newsp, pregs, 0, 0, 0); -} - -/* - * This is trivial, and on the face of it looks like it - * could equally well be done in user mode. - * - * Not so, for quite unobvious reasons - register pressure. - * In user mode vfork() cannot have a stack frame, and if - * done by calling the "clone()" system call directly, you - * do not have enough call-clobbered registers to hold all - * the information you need. - */ -asmlinkage int sys_vfork(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0); -} - -/* - * sys_execve() executes a new program. - */ -asmlinkage int sys_execve(char *ufilename, char **uargv, - char **uenvp, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs *pregs) -{ - int error; - char *filename; - - lock_kernel(); - filename = getname((char __user *)ufilename); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - - error = do_execve(filename, - (char __user * __user *)uargv, - (char __user * __user *)uenvp, - pregs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - unlock_kernel(); - return error; -} - -/* - * These bracket the sleeping functions.. - */ -extern void interruptible_sleep_on(wait_queue_head_t *q); - -#define mid_sched ((unsigned long) interruptible_sleep_on) - -static int in_sh64_switch_to(unsigned long pc) -{ - extern char __sh64_switch_to_end; - /* For a sleeping task, the PC is somewhere in the middle of the function, - so we don't have to worry about masking the LSB off */ - return (pc >= (unsigned long) sh64_switch_to) && - (pc < (unsigned long) &__sh64_switch_to_end); -} - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long schedule_fp; - unsigned long sh64_switch_to_fp; - unsigned long schedule_caller_pc; - unsigned long pc; - - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - - /* - * The same comment as on the Alpha applies here, too ... - */ - pc = thread_saved_pc(p); - -#ifdef CONFIG_FRAME_POINTER - if (in_sh64_switch_to(pc)) { - sh64_switch_to_fp = (long) p->thread.sp; - /* r14 is saved at offset 4 in the sh64_switch_to frame */ - schedule_fp = *(unsigned long *) (long)(sh64_switch_to_fp + 4); - - /* and the caller of 'schedule' is (currently!) saved at offset 24 - in the frame of schedule (from disasm) */ - schedule_caller_pc = *(unsigned long *) (long)(schedule_fp + 24); - return schedule_caller_pc; - } -#endif - return pc; -} - -/* Provide a /proc/asids file that lists out the - ASIDs currently associated with the processes. (If the DM.PC register is - examined through the debug link, this shows ASID + PC. To make use of this, - the PID->ASID relationship needs to be known. This is primarily for - debugging.) - */ - -#if defined(CONFIG_SH64_PROC_ASIDS) -static int -asids_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) -{ - int len=0; - struct task_struct *p; - read_lock(&tasklist_lock); - for_each_process(p) { - int pid = p->pid; - struct mm_struct *mm; - if (!pid) continue; - mm = p->mm; - if (mm) { - unsigned long asid, context; - context = mm->context; - asid = (context & 0xff); - len += sprintf(buf+len, "%5d : %02lx\n", pid, asid); - } else { - len += sprintf(buf+len, "%5d : (none)\n", pid); - } - } - read_unlock(&tasklist_lock); - *eof = 1; - return len; -} - -static int __init register_proc_asids(void) -{ - create_proc_read_entry("asids", 0, NULL, asids_proc_info, NULL); - return 0; -} -__initcall(register_proc_asids); -#endif diff -puN arch/sh64/kernel/ptrace.c~git-sh /dev/null --- a/arch/sh64/kernel/ptrace.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/ptrace.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * Started from SH3/4 version: - * SuperH version: Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka - * - * Original x86 implementation: - * By Ross Biro 1/23/92 - * edited by Linus Torvalds - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -/* This mask defines the bits of the SR which the user is not allowed to - change, which are everything except S, Q, M, PR, SZ, FR. */ -#define SR_MASK (0xffff8cfd) - -/* - * does not yet catch signals sent when the child dies. - * in exit.c or in signal.c. - */ - -/* - * This routine will get a word from the user area in the process kernel stack. - */ -static inline int get_stack_long(struct task_struct *task, int offset) -{ - unsigned char *stack; - - stack = (unsigned char *)(task->thread.uregs); - stack += offset; - return (*((int *)stack)); -} - -static inline unsigned long -get_fpu_long(struct task_struct *task, unsigned long addr) -{ - unsigned long tmp; - struct pt_regs *regs; - regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - - if (!tsk_used_math(task)) { - if (addr == offsetof(struct user_fpu_struct, fpscr)) { - tmp = FPSCR_INIT; - } else { - tmp = 0xffffffffUL; /* matches initial value in fpu.c */ - } - return tmp; - } - - if (last_task_used_math == task) { - grab_fpu(); - fpsave(&task->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - tmp = ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)]; - return tmp; -} - -/* - * This routine will put a word into the user area in the process kernel stack. - */ -static inline int put_stack_long(struct task_struct *task, int offset, - unsigned long data) -{ - unsigned char *stack; - - stack = (unsigned char *)(task->thread.uregs); - stack += offset; - *(unsigned long *) stack = data; - return 0; -} - -static inline int -put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) -{ - struct pt_regs *regs; - - regs = (struct pt_regs*)((unsigned char *)task + THREAD_SIZE) - 1; - - if (!tsk_used_math(task)) { - fpinit(&task->thread.fpu.hard); - set_stopped_child_used_math(task); - } else if (last_task_used_math == task) { - grab_fpu(); - fpsave(&task->thread.fpu.hard); - release_fpu(); - last_task_used_math = 0; - regs->sr |= SR_FD; - } - - ((long *)&task->thread.fpu)[addr / sizeof(unsigned long)] = data; - return 0; -} - - -long arch_ptrace(struct task_struct *child, long request, long addr, long data) -{ - int ret; - - 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: - ret = generic_ptrace_peekdata(child, addr, data); - break; - - /* read the word at location addr in the USER area. */ - case PTRACE_PEEKUSR: { - unsigned long tmp; - - ret = -EIO; - if ((addr & 3) || addr < 0) - break; - - if (addr < sizeof(struct pt_regs)) - tmp = get_stack_long(child, addr); - else if ((addr >= offsetof(struct user, fpu)) && - (addr < offsetof(struct user, u_fpvalid))) { - tmp = get_fpu_long(child, addr - offsetof(struct user, fpu)); - } else if (addr == offsetof(struct user, u_fpvalid)) { - tmp = !!tsk_used_math(child); - } else { - break; - } - ret = put_user(tmp, (unsigned long *)data); - 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 = generic_ptrace_pokedata(child, addr, data); - break; - - case PTRACE_POKEUSR: - /* write the word at location addr in the USER area. We must - disallow any changes to certain SR bits or u_fpvalid, since - this could crash the kernel or result in a security - loophole. */ - ret = -EIO; - if ((addr & 3) || addr < 0) - break; - - if (addr < sizeof(struct pt_regs)) { - /* Ignore change of top 32 bits of SR */ - if (addr == offsetof (struct pt_regs, sr)+4) - { - ret = 0; - break; - } - /* If lower 32 bits of SR, ignore non-user bits */ - if (addr == offsetof (struct pt_regs, sr)) - { - long cursr = get_stack_long(child, addr); - data &= ~(SR_MASK); - data |= (cursr & SR_MASK); - } - ret = put_stack_long(child, addr, data); - } - else if ((addr >= offsetof(struct user, fpu)) && - (addr < offsetof(struct user, u_fpvalid))) { - ret = put_fpu_long(child, addr - offsetof(struct user, fpu), data); - } - 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; - 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 */ - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - struct pt_regs *regs; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - regs = child->thread.uregs; - - regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ - - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - - default: - ret = ptrace_request(child, request, addr, data); - break; - } - return ret; -} - -asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) -{ - extern void poke_real_address_q(unsigned long long addr, unsigned long long data); -#define WPC_DBRMODE 0x0d104008 - static int first_call = 1; - - lock_kernel(); - if (first_call) { - /* Set WPC.DBRMODE to 0. This makes all debug events get - * delivered through RESVEC, i.e. into the handlers in entry.S. - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE - * would normally be left set to 1, which makes debug events get - * delivered through DBRVEC, i.e. into the remote gdb's - * handlers. This prevents ptrace getting them, and confuses - * the remote gdb.) */ - printk("DBRMODE set to 0 to permit native debugging\n"); - poke_real_address_q(WPC_DBRMODE, 0); - first_call = 0; - } - unlock_kernel(); - - return sys_ptrace(request, pid, addr, data); -} - -asmlinkage void syscall_trace(void) -{ - struct task_struct *tsk = current; - - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(tsk->ptrace & PT_PTRACED)) - return; - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * 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 (tsk->exit_code) { - send_sig(tsk->exit_code, tsk, 1); - tsk->exit_code = 0; - } -} - -/* Called with interrupts disabled */ -asmlinkage void do_single_step(unsigned long long vec, struct pt_regs *regs) -{ - /* This is called after a single step exception (DEBUGSS). - There is no need to change the PC, as it is a post-execution - exception, as entry.S does not do anything to the PC for DEBUGSS. - We need to clear the Single Step setting in SR to avoid - continually stepping. */ - local_irq_enable(); - regs->sr &= ~SR_SSTEP; - force_sig(SIGTRAP, current); -} - -/* Called with interrupts disabled */ -asmlinkage void do_software_break_point(unsigned long long vec, - struct pt_regs *regs) -{ - /* We need to forward step the PC, to counteract the backstep done - in signal.c. */ - local_irq_enable(); - force_sig(SIGTRAP, current); - regs->pc += 4; -} - -/* - * Called by kernel/ptrace.c when detaching.. - * - * Make sure single step bits etc are not set. - */ -void ptrace_disable(struct task_struct *child) -{ - /* nothing to do.. */ -} diff -puN arch/sh64/kernel/semaphore.c~git-sh /dev/null --- a/arch/sh64/kernel/semaphore.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Just taken from alpha implementation. - * This can't work well, perhaps. - */ -/* - * Generic semaphore code. Buyer beware. Do your own - * specific changes in - */ - -#include -#include -#include -#include -#include -#include -#include - -spinlock_t semaphore_wake_lock; - -/* - * Semaphores are implemented using a two-way counter: - * The "count" variable is decremented for each process - * that tries to sleep, while the "waking" variable is - * incremented when the "up()" code goes to wake up waiting - * processes. - * - * Notably, the inline "up()" and "down()" functions can - * efficiently test if they need to do any extra work (up - * needs to do something only if count was negative before - * the increment operation. - * - * waking_non_zero() (from asm/semaphore.h) must execute - * atomically. - * - * When __up() is called, the count was negative before - * incrementing it, and we need to wake up somebody. - * - * This routine adds one to the count of processes that need to - * wake up and exit. ALL waiting processes actually wake up but - * only the one that gets to the "waking" field first will gate - * through and acquire the semaphore. The others will go back - * to sleep. - * - * Note that these functions are only called when there is - * contention on the lock, and as such all this is the - * "non-critical" part of the whole semaphore business. The - * critical part is the inline stuff in - * where we want to avoid any extra jumps and calls. - */ -void __up(struct semaphore *sem) -{ - wake_one_more(sem); - wake_up(&sem->wait); -} - -/* - * Perform the "down" function. Return zero for semaphore acquired, - * return negative for signalled out of the function. - * - * If called from __down, the return is ignored and the wait loop is - * not interruptible. This means that a task waiting on a semaphore - * using "down()" cannot be killed until someone does an "up()" on - * the semaphore. - * - * If called from __down_interruptible, the return value gets checked - * upon return. If the return value is negative then the task continues - * with the negative value in the return register (it can be tested by - * the caller). - * - * Either form may be used in conjunction with "up()". - * - */ - -#define DOWN_VAR \ - struct task_struct *tsk = current; \ - wait_queue_t wait; \ - init_waitqueue_entry(&wait, tsk); - -#define DOWN_HEAD(task_state) \ - \ - \ - tsk->state = (task_state); \ - add_wait_queue(&sem->wait, &wait); \ - \ - /* \ - * Ok, we're set up. sem->count is known to be less than zero \ - * so we must wait. \ - * \ - * We can let go the lock for purposes of waiting. \ - * We re-acquire it after awaking so as to protect \ - * all semaphore operations. \ - * \ - * If "up()" is called before we call waking_non_zero() then \ - * we will catch it right away. If it is called later then \ - * we will have to go through a wakeup cycle to catch it. \ - * \ - * Multiple waiters contend for the semaphore lock to see \ - * who gets to gate through and who has to wait some more. \ - */ \ - for (;;) { - -#define DOWN_TAIL(task_state) \ - tsk->state = (task_state); \ - } \ - tsk->state = TASK_RUNNING; \ - remove_wait_queue(&sem->wait, &wait); - -void __sched __down(struct semaphore * sem) -{ - DOWN_VAR - DOWN_HEAD(TASK_UNINTERRUPTIBLE) - if (waking_non_zero(sem)) - break; - schedule(); - DOWN_TAIL(TASK_UNINTERRUPTIBLE) -} - -int __sched __down_interruptible(struct semaphore * sem) -{ - int ret = 0; - DOWN_VAR - DOWN_HEAD(TASK_INTERRUPTIBLE) - - ret = waking_non_zero_interruptible(sem, tsk); - if (ret) - { - if (ret == 1) - /* ret != 0 only if we get interrupted -arca */ - ret = 0; - break; - } - schedule(); - DOWN_TAIL(TASK_INTERRUPTIBLE) - return ret; -} - -int __down_trylock(struct semaphore * sem) -{ - return waking_non_zero_trylock(sem); -} diff -puN arch/sh64/kernel/setup.c~git-sh /dev/null --- a/arch/sh64/kernel/setup.c +++ /dev/null @@ -1,379 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/setup.c - * - * sh64 Arch Support - * - * This file handles the architecture-dependent parts of initialization - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * benedict.gaster@superh.com: 2nd May 2002 - * Modified to use the empty_zero_page to pass command line arguments. - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - * - * lethal@linux-sh.org: 15th May 2003 - * Added generic procfs cpuinfo reporting. Make boards just export their name. - * - * lethal@linux-sh.org: 25th May 2003 - * Added generic get_cpu_subtype() for subtype reporting from cpu_data->type. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct screen_info screen_info; - -#ifdef CONFIG_BLK_DEV_RAM -extern int rd_doload; /* 1 = load ramdisk, 0 = don't load */ -extern int rd_prompt; /* 1 = prompt for ramdisk, 0 = don't prompt */ -extern int rd_image_start; /* starting block # of image */ -#endif - -extern int root_mountflags; -extern char *get_system_type(void); -extern void platform_setup(void); -extern void platform_monitor(void); -extern void platform_reserve(void); -extern int sh64_cache_init(void); -extern int sh64_tlb_init(void); - -#define RAMDISK_IMAGE_START_MASK 0x07FF -#define RAMDISK_PROMPT_FLAG 0x8000 -#define RAMDISK_LOAD_FLAG 0x4000 - -static char __initdata command_line[COMMAND_LINE_SIZE] = { 0, }; -unsigned long long memory_start = CONFIG_MEMORY_START; -unsigned long long memory_end = CONFIG_MEMORY_START + (CONFIG_MEMORY_SIZE_IN_MB * 1024 * 1024); - -struct sh_cpuinfo boot_cpu_data; - -static inline void parse_mem_cmdline (char ** cmdline_p) -{ - char c = ' ', *to = command_line, *from = COMMAND_LINE; - int len = 0; - - /* Save unparsed command line copy for /proc/cmdline */ - memcpy(boot_command_line, COMMAND_LINE, COMMAND_LINE_SIZE); - boot_command_line[COMMAND_LINE_SIZE-1] = '\0'; - - for (;;) { - /* - * "mem=XXX[kKmM]" defines a size of memory. - */ - if (c == ' ' && !memcmp(from, "mem=", 4)) { - if (to != command_line) - to--; - { - unsigned long mem_size; - - mem_size = memparse(from+4, &from); - memory_end = memory_start + mem_size; - } - } - c = *(from++); - if (!c) - break; - if (COMMAND_LINE_SIZE <= ++len) - break; - *(to++) = c; - } - *to = '\0'; - - *cmdline_p = command_line; -} - -static void __init sh64_cpu_type_detect(void) -{ - extern unsigned long long peek_real_address_q(unsigned long long addr); - unsigned long long cir; - /* Do peeks in real mode to avoid having to set up a mapping for the - WPC registers. On SH5-101 cut2, such a mapping would be exposed to - an address translation erratum which would make it hard to set up - correctly. */ - cir = peek_real_address_q(0x0d000008); - - if ((cir & 0xffff) == 0x5103) { - boot_cpu_data.type = CPU_SH5_103; - } else if (((cir >> 32) & 0xffff) == 0x51e2) { - /* CPU.VCR aliased at CIR address on SH5-101 */ - boot_cpu_data.type = CPU_SH5_101; - } else { - boot_cpu_data.type = CPU_SH_NONE; - } -} - -void __init setup_arch(char **cmdline_p) -{ - unsigned long bootmap_size, i; - unsigned long first_pfn, start_pfn, last_pfn, pages; - -#ifdef CONFIG_EARLY_PRINTK - extern void enable_early_printk(void); - - /* - * Setup Early SCIF console - */ - enable_early_printk(); -#endif - - /* - * Setup TLB mappings - */ - sh64_tlb_init(); - - /* - * Caches are already initialized by the time we get here, so we just - * fill in cpu_data info for the caches. - */ - sh64_cache_init(); - - platform_setup(); - platform_monitor(); - - sh64_cpu_type_detect(); - - ROOT_DEV = old_decode_dev(ORIG_ROOT_DEV); - -#ifdef CONFIG_BLK_DEV_RAM - rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK; - rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0); - rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0); -#endif - - if (!MOUNT_ROOT_RDONLY) - root_mountflags &= ~MS_RDONLY; - init_mm.start_code = (unsigned long) _text; - init_mm.end_code = (unsigned long) _etext; - init_mm.end_data = (unsigned long) _edata; - init_mm.brk = (unsigned long) _end; - - code_resource.start = __pa(_text); - code_resource.end = __pa(_etext)-1; - data_resource.start = __pa(_etext); - data_resource.end = __pa(_edata)-1; - - parse_mem_cmdline(cmdline_p); - - /* - * Find the lowest and highest page frame numbers we have available - */ - first_pfn = PFN_DOWN(memory_start); - last_pfn = PFN_DOWN(memory_end); - pages = last_pfn - first_pfn; - - /* - * Partially used pages are not usable - thus - * we are rounding upwards: - */ - start_pfn = PFN_UP(__pa(_end)); - - /* - * Find a proper area for the bootmem bitmap. After this - * bootstrap step all allocations (until the page allocator - * is intact) must be done via bootmem_alloc(). - */ - bootmap_size = init_bootmem_node(NODE_DATA(0), start_pfn, - first_pfn, - last_pfn); - /* - * Round it up. - */ - bootmap_size = PFN_PHYS(PFN_UP(bootmap_size)); - - /* - * Register fully available RAM pages with the bootmem allocator. - */ - free_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn), PFN_PHYS(pages)); - - /* - * Reserve all kernel sections + bootmem bitmap + a guard page. - */ - reserve_bootmem_node(NODE_DATA(0), PFN_PHYS(first_pfn), - (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE) - PFN_PHYS(first_pfn)); - - /* - * Reserve platform dependent sections - */ - platform_reserve(); - -#ifdef CONFIG_BLK_DEV_INITRD - if (LOADER_TYPE && INITRD_START) { - if (INITRD_START + INITRD_SIZE <= (PFN_PHYS(last_pfn))) { - reserve_bootmem_node(NODE_DATA(0), INITRD_START + __MEMORY_START, INITRD_SIZE); - - initrd_start = (long) INITRD_START + PAGE_OFFSET + __MEMORY_START; - initrd_end = initrd_start + INITRD_SIZE; - } else { - printk("initrd extends beyond end of memory " - "(0x%08lx > 0x%08lx)\ndisabling initrd\n", - (long) INITRD_START + INITRD_SIZE, - PFN_PHYS(last_pfn)); - initrd_start = 0; - } - } -#endif - - /* - * Claim all RAM, ROM, and I/O resources. - */ - - /* Kernel RAM */ - request_resource(&iomem_resource, &code_resource); - request_resource(&iomem_resource, &data_resource); - - /* Other KRAM space */ - for (i = 0; i < STANDARD_KRAM_RESOURCES - 2; i++) - request_resource(&iomem_resource, - &platform_parms.kram_res_p[i]); - - /* XRAM space */ - for (i = 0; i < STANDARD_XRAM_RESOURCES; i++) - request_resource(&iomem_resource, - &platform_parms.xram_res_p[i]); - - /* ROM space */ - for (i = 0; i < STANDARD_ROM_RESOURCES; i++) - request_resource(&iomem_resource, - &platform_parms.rom_res_p[i]); - - /* I/O space */ - for (i = 0; i < STANDARD_IO_RESOURCES; i++) - request_resource(&ioport_resource, - &platform_parms.io_res_p[i]); - - -#ifdef CONFIG_VT -#if defined(CONFIG_VGA_CONSOLE) - conswitchp = &vga_con; -#elif defined(CONFIG_DUMMY_CONSOLE) - conswitchp = &dummy_con; -#endif -#endif - - printk("Hardware FPU: %s\n", fpu_in_use ? "enabled" : "disabled"); - - paging_init(); -} - -void __xchg_called_with_bad_pointer(void) -{ - printk(KERN_EMERG "xchg() called with bad pointer !\n"); -} - -static struct cpu cpu[1]; - -static int __init topology_init(void) -{ - return register_cpu(cpu, 0); -} - -subsys_initcall(topology_init); - -/* - * Get CPU information - */ -static const char *cpu_name[] = { - [CPU_SH5_101] = "SH5-101", - [CPU_SH5_103] = "SH5-103", - [CPU_SH_NONE] = "Unknown", -}; - -const char *get_cpu_subtype(void) -{ - return cpu_name[boot_cpu_data.type]; -} - -#ifdef CONFIG_PROC_FS -static int show_cpuinfo(struct seq_file *m,void *v) -{ - unsigned int cpu = smp_processor_id(); - - if (!cpu) - seq_printf(m, "machine\t\t: %s\n", get_system_type()); - - seq_printf(m, "processor\t: %d\n", cpu); - seq_printf(m, "cpu family\t: SH-5\n"); - seq_printf(m, "cpu type\t: %s\n", get_cpu_subtype()); - - seq_printf(m, "icache size\t: %dK-bytes\n", - (boot_cpu_data.icache.ways * - boot_cpu_data.icache.sets * - boot_cpu_data.icache.linesz) >> 10); - seq_printf(m, "dcache size\t: %dK-bytes\n", - (boot_cpu_data.dcache.ways * - boot_cpu_data.dcache.sets * - boot_cpu_data.dcache.linesz) >> 10); - seq_printf(m, "itlb entries\t: %d\n", boot_cpu_data.itlb.entries); - seq_printf(m, "dtlb entries\t: %d\n", boot_cpu_data.dtlb.entries); - -#define PRINT_CLOCK(name, value) \ - seq_printf(m, name " clock\t: %d.%02dMHz\n", \ - ((value) / 1000000), ((value) % 1000000)/10000) - - PRINT_CLOCK("cpu", boot_cpu_data.cpu_clock); - PRINT_CLOCK("bus", boot_cpu_data.bus_clock); - PRINT_CLOCK("module", boot_cpu_data.module_clock); - - seq_printf(m, "bogomips\t: %lu.%02lu\n\n", - (loops_per_jiffy*HZ+2500)/500000, - ((loops_per_jiffy*HZ+2500)/5000) % 100); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return (void*)(*pos == 0); -} -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - return NULL; -} -static void c_stop(struct seq_file *m, void *v) -{ -} -struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; -#endif /* CONFIG_PROC_FS */ diff -puN arch/sh64/kernel/sh_ksyms.c~git-sh /dev/null --- a/arch/sh64/kernel/sh_ksyms.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/sh_ksyms.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -extern int dump_fpu(struct pt_regs *, elf_fpregset_t *); - -/* platform dependent support */ -EXPORT_SYMBOL(dump_fpu); -EXPORT_SYMBOL(kernel_thread); - -/* Networking helper routines. */ -EXPORT_SYMBOL(csum_partial_copy_nocheck); - -#ifdef CONFIG_VT -EXPORT_SYMBOL(screen_info); -#endif - -EXPORT_SYMBOL(__down); -EXPORT_SYMBOL(__down_trylock); -EXPORT_SYMBOL(__up); -EXPORT_SYMBOL(__put_user_asm_l); -EXPORT_SYMBOL(__get_user_asm_l); -EXPORT_SYMBOL(__copy_user); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(udelay); -EXPORT_SYMBOL(__udelay); -EXPORT_SYMBOL(ndelay); -EXPORT_SYMBOL(__ndelay); -EXPORT_SYMBOL(flush_dcache_page); -EXPORT_SYMBOL(sh64_page_clear); - -/* Ugh. These come in from libgcc.a at link time. */ -#define DECLARE_EXPORT(name) extern void name(void);EXPORT_SYMBOL(name) - -DECLARE_EXPORT(__sdivsi3); -DECLARE_EXPORT(__muldi3); -DECLARE_EXPORT(__udivsi3); diff -puN arch/sh64/kernel/signal.c~git-sh /dev/null --- a/arch/sh64/kernel/signal.c +++ /dev/null @@ -1,750 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/signal.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * Started from sh version. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define REG_RET 9 -#define REG_ARG1 2 -#define REG_ARG2 3 -#define REG_ARG3 4 -#define REG_SP 15 -#define REG_PR 18 -#define REF_REG_RET regs->regs[REG_RET] -#define REF_REG_SP regs->regs[REG_SP] -#define DEREF_REG_PR regs->regs[REG_PR] - -#define DEBUG_SIG 0 - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); - -/* - * Atomically swap in the new signal mask, and wait for a signal. - */ - -asmlinkage int -sys_sigsuspend(old_sigset_t mask, - unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - sigset_t saveset; - - mask &= _BLOCKABLE; - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - siginitset(¤t->blocked, mask); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - REF_REG_RET = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - regs->pc += 4; /* because sys_sigreturn decrements the pc */ - if (do_signal(regs, &saveset)) { - /* pc now points at signal handler. Need to decrement - it because entry.S will increment it. */ - regs->pc -= 4; - return -EINTR; - } - } -} - -asmlinkage int -sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, - unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, - struct pt_regs * regs) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - REF_REG_RET = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - regs->pc += 4; /* because sys_sigreturn decrements the pc */ - if (do_signal(regs, &saveset)) { - /* pc now points at signal handler. Need to decrement - it because entry.S will increment it. */ - regs->pc -= 4; - return -EINTR; - } - } -} - -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, - unsigned long r4, unsigned long r5, unsigned long r6, - unsigned long r7, - struct pt_regs * regs) -{ - return do_sigaltstack(uss, uoss, REF_REG_SP); -} - - -/* - * Do a signal return; undo the signal stack. - */ - -struct sigframe -{ - struct sigcontext sc; - unsigned long extramask[_NSIG_WORDS-1]; - long long retcode[2]; -}; - -struct rt_sigframe -{ - struct siginfo __user *pinfo; - void *puc; - struct siginfo info; - struct ucontext uc; - long long retcode[2]; -}; - -#ifdef CONFIG_SH_FPU -static inline int -restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - int fpvalid; - - err |= __get_user (fpvalid, &sc->sc_fpvalid); - conditional_used_math(fpvalid); - if (! fpvalid) - return err; - - if (current == last_task_used_math) { - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - err |= __copy_from_user(¤t->thread.fpu.hard, &sc->sc_fpregs[0], - (sizeof(long long) * 32) + (sizeof(int) * 1)); - - return err; -} - -static inline int -setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{ - int err = 0; - int fpvalid; - - fpvalid = !!used_math(); - err |= __put_user(fpvalid, &sc->sc_fpvalid); - if (! fpvalid) - return err; - - if (current == last_task_used_math) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - err |= __copy_to_user(&sc->sc_fpregs[0], ¤t->thread.fpu.hard, - (sizeof(long long) * 32) + (sizeof(int) * 1)); - clear_used_math(); - - return err; -} -#else -static inline int -restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{} -static inline int -setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user *sc) -{} -#endif - -static int -restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, long long *r2_p) -{ - unsigned int err = 0; - unsigned long long current_sr, new_sr; -#define SR_MASK 0xffff8cfd - -#define COPY(x) err |= __get_user(regs->x, &sc->sc_##x) - - COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); - COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); - COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); - COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); - COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); - COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); - COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); - COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); - COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); - COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); - COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); - COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); - COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); - COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); - COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); - - /* Prevent the signal handler manipulating SR in a way that can - crash the kernel. i.e. only allow S, Q, M, PR, SZ, FR to be - modified */ - current_sr = regs->sr; - err |= __get_user(new_sr, &sc->sc_sr); - regs->sr &= SR_MASK; - regs->sr |= (new_sr & ~SR_MASK); - - COPY(pc); - -#undef COPY - - /* Must do this last in case it sets regs->sr.fd (i.e. after rest of sr - * has been restored above.) */ - err |= restore_sigcontext_fpu(regs, sc); - - regs->syscall_nr = -1; /* disable syscall checks */ - err |= __get_user(*r2_p, &sc->sc_regs[REG_RET]); - return err; -} - -asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - struct sigframe __user *frame = (struct sigframe __user *) (long) REF_REG_SP; - sigset_t set; - long long ret; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - if (__get_user(set.sig[0], &frame->sc.oldmask) - || (_NSIG_WORDS > 1 - && __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); - - if (restore_sigcontext(regs, &frame->sc, &ret)) - goto badframe; - regs->pc -= 4; - - return (int) ret; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3, - unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs * regs) -{ - struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (long) REF_REG_SP; - sigset_t set; - stack_t __user st; - long long ret; - - if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) - goto badframe; - - 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); - - if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret)) - goto badframe; - regs->pc -= 4; - - if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st))) - goto badframe; - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - do_sigaltstack(&st, NULL, REF_REG_SP); - - return (int) ret; - -badframe: - force_sig(SIGSEGV, current); - return 0; -} - -/* - * Set up a signal frame. - */ - -static int -setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err = 0; - - /* Do this first, otherwise is this sets sr->fd, that value isn't preserved. */ - err |= setup_sigcontext_fpu(regs, sc); - -#define COPY(x) err |= __put_user(regs->x, &sc->sc_##x) - - COPY(regs[0]); COPY(regs[1]); COPY(regs[2]); COPY(regs[3]); - COPY(regs[4]); COPY(regs[5]); COPY(regs[6]); COPY(regs[7]); - COPY(regs[8]); COPY(regs[9]); COPY(regs[10]); COPY(regs[11]); - COPY(regs[12]); COPY(regs[13]); COPY(regs[14]); COPY(regs[15]); - COPY(regs[16]); COPY(regs[17]); COPY(regs[18]); COPY(regs[19]); - COPY(regs[20]); COPY(regs[21]); COPY(regs[22]); COPY(regs[23]); - COPY(regs[24]); COPY(regs[25]); COPY(regs[26]); COPY(regs[27]); - COPY(regs[28]); COPY(regs[29]); COPY(regs[30]); COPY(regs[31]); - COPY(regs[32]); COPY(regs[33]); COPY(regs[34]); COPY(regs[35]); - COPY(regs[36]); COPY(regs[37]); COPY(regs[38]); COPY(regs[39]); - COPY(regs[40]); COPY(regs[41]); COPY(regs[42]); COPY(regs[43]); - COPY(regs[44]); COPY(regs[45]); COPY(regs[46]); COPY(regs[47]); - COPY(regs[48]); COPY(regs[49]); COPY(regs[50]); COPY(regs[51]); - COPY(regs[52]); COPY(regs[53]); COPY(regs[54]); COPY(regs[55]); - COPY(regs[56]); COPY(regs[57]); COPY(regs[58]); COPY(regs[59]); - COPY(regs[60]); COPY(regs[61]); COPY(regs[62]); - COPY(tregs[0]); COPY(tregs[1]); COPY(tregs[2]); COPY(tregs[3]); - COPY(tregs[4]); COPY(tregs[5]); COPY(tregs[6]); COPY(tregs[7]); - COPY(sr); COPY(pc); - -#undef COPY - - err |= __put_user(mask, &sc->oldmask); - - return err; -} - -/* - * Determine which stack to use.. - */ -static inline void __user * -get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size) -{ - if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp)) - sp = current->sas_ss_sp + current->sas_ss_size; - - return (void __user *)((sp - frame_size) & -8ul); -} - -void sa_default_restorer(void); /* See comments below */ -void sa_default_rt_restorer(void); /* See comments below */ - -static void setup_frame(int sig, struct k_sigaction *ka, - sigset_t *set, struct pt_regs *regs) -{ - struct sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= setup_sigcontext(&frame->sc, regs, set->sig[0]); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - if (_NSIG_WORDS > 1) { - err |= __copy_to_user(frame->extramask, &set->sig[1], - sizeof(frame->extramask)); } - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - - /* - * On SH5 all edited pointers are subject to NEFF - */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - } else { - /* - * Different approach on SH5. - * . Endianness independent asm code gets placed in entry.S . - * This is limited to four ASM instructions corresponding - * to two long longs in size. - * . err checking is done on the else branch only - * . flush_icache_range() is called upon __put_user() only - * . all edited pointers are subject to NEFF - * . being code, linker turns ShMedia bit on, always - * dereference index -1. - */ - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - - if (__copy_to_user(frame->retcode, - (unsigned long long)sa_default_restorer & (~1), 16) != 0) - goto give_sigsegv; - - /* Cohere the trampoline with the I-cache. */ - flush_cache_sigtramp(DEREF_REG_PR-1, DEREF_REG_PR-1+16); - } - - /* - * Set up registers for signal handler. - * All edited pointers are subject to NEFF. - */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; - regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ - - /* FIXME: - The glibc profiling support for SH-5 needs to be passed a sigcontext - so it can retrieve the PC. At some point during 2003 the glibc - support was changed to receive the sigcontext through the 2nd - argument, but there are still versions of libc.so in use that use - the 3rd argument. Until libc.so is stabilised, pass the sigcontext - through both 2nd and 3rd arguments. - */ - - regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; - regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; - - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; - - set_fs(USER_DS); - -#if DEBUG_SIG - /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif - - return; - -give_sigsegv: - force_sigsegv(sig, current); -} - -static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, - sigset_t *set, struct pt_regs *regs) -{ - struct rt_sigframe __user *frame; - int err = 0; - int signal; - - frame = get_sigframe(ka, regs->regs[REG_SP], sizeof(*frame)); - - if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) - goto give_sigsegv; - - signal = current_thread_info()->exec_domain - && current_thread_info()->exec_domain->signal_invmap - && sig < 32 - ? current_thread_info()->exec_domain->signal_invmap[sig] - : sig; - - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); - err |= copy_siginfo_to_user(&frame->info, info); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __put_user((void *)current->sas_ss_sp, - &frame->uc.uc_stack.ss_sp); - err |= __put_user(sas_ss_flags(regs->regs[REG_SP]), - &frame->uc.uc_stack.ss_flags); - err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size); - err |= setup_sigcontext(&frame->uc.uc_mcontext, - regs, set->sig[0]); - err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - - /* Give up earlier as i386, in case */ - if (err) - goto give_sigsegv; - - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1; - - /* - * On SH5 all edited pointers are subject to NEFF - */ - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - } else { - /* - * Different approach on SH5. - * . Endianness independent asm code gets placed in entry.S . - * This is limited to four ASM instructions corresponding - * to two long longs in size. - * . err checking is done on the else branch only - * . flush_icache_range() is called upon __put_user() only - * . all edited pointers are subject to NEFF - * . being code, linker turns ShMedia bit on, always - * dereference index -1. - */ - - DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; - DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? - (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; - - if (__copy_to_user(frame->retcode, - (unsigned long long)sa_default_rt_restorer & (~1), 16) != 0) - goto give_sigsegv; - - flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); - } - - /* - * Set up registers for signal handler. - * All edited pointers are subject to NEFF. - */ - regs->regs[REG_SP] = (unsigned long) frame; - regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ? - (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP]; - regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ - regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; - regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; - regs->pc = (unsigned long) ka->sa.sa_handler; - regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc; - - set_fs(USER_DS); - -#if DEBUG_SIG - /* Broken %016Lx */ - printk("SIG deliver (#%d,%s:%d): sp=%p pc=%08Lx%08Lx link=%08Lx%08Lx\n", - signal, - current->comm, current->pid, frame, - regs->pc >> 32, regs->pc & 0xffffffff, - DEREF_REG_PR >> 32, DEREF_REG_PR & 0xffffffff); -#endif - - return; - -give_sigsegv: - force_sigsegv(sig, current); -} - -/* - * OK, we're invoking a handler - */ - -static void -handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - sigset_t *oldset, struct pt_regs * regs) -{ - /* Are we from a system call? */ - if (regs->syscall_nr >= 0) { - /* If so, check system call restarting.. */ - switch (regs->regs[REG_RET]) { - case -ERESTART_RESTARTBLOCK: - case -ERESTARTNOHAND: - regs->regs[REG_RET] = -EINTR; - break; - - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[REG_RET] = -EINTR; - break; - } - /* fallthrough */ - case -ERESTARTNOINTR: - /* Decode syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - } - } - - /* Set up the stack frame */ - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame(sig, ka, info, oldset, regs); - else - setup_frame(sig, ka, oldset, regs); - - 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); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) -{ - siginfo_t info; - int signr; - struct k_sigaction ka; - - /* - * 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(regs)) - return 1; - - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else if (!oldset) - oldset = ¤t->blocked; - - signr = get_signal_to_deliver(&info, &ka, regs, 0); - - if (signr > 0) { - /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, oldset, regs); - - /* - * If a signal was successfully delivered, the saved sigmask - * is in its frame, and we can clear the TIF_RESTORE_SIGMASK - * flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - return 1; - } - -no_signal: - /* Did we come from a system call? */ - if (regs->syscall_nr >= 0) { - /* Restart the system call - no handlers present */ - switch (regs->regs[REG_RET]) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - /* Decode Syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - break; - - case -ERESTART_RESTARTBLOCK: - regs->regs[REG_RET] = __NR_restart_syscall; - regs->pc -= 4; - break; - } - } - - /* No signal to deliver -- 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); - } - - return 0; -} diff -puN arch/sh64/kernel/switchto.S~git-sh /dev/null --- a/arch/sh64/kernel/switchto.S +++ /dev/null @@ -1,198 +0,0 @@ -/* - * arch/sh64/kernel/switchto.S - * - * sh64 context switch - * - * Copyright (C) 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. -*/ - - .section .text..SHmedia32,"ax" - .little - - .balign 32 - - .type sh64_switch_to,@function - .global sh64_switch_to - .global __sh64_switch_to_end -sh64_switch_to: - -/* Incoming args - r2 - prev - r3 - &prev->thread - r4 - next - r5 - &next->thread - - Outgoing results - r2 - last (=prev) : this just stays in r2 throughout - - Want to create a full (struct pt_regs) on the stack to allow backtracing - functions to work. However, we only need to populate the callee-save - register slots in this structure; since we're a function our ancestors must - have themselves preserved all caller saved state in the stack. This saves - some wasted effort since we won't need to look at the values. - - In particular, all caller-save registers are immediately available for - scratch use. - -*/ - -#define FRAME_SIZE (76*8 + 8) - - movi FRAME_SIZE, r0 - sub.l r15, r0, r15 - ! Do normal-style register save to support backtrace - - st.l r15, 0, r18 ! save link reg - st.l r15, 4, r14 ! save fp - add.l r15, r63, r14 ! setup frame pointer - - ! hopefully this looks normal to the backtrace now. - - addi.l r15, 8, r1 ! base of pt_regs - addi.l r1, 24, r0 ! base of pt_regs.regs - addi.l r0, (63*8), r8 ! base of pt_regs.trregs - - /* Note : to be fixed? - struct pt_regs is really designed for holding the state on entry - to an exception, i.e. pc,sr,regs etc. However, for the context - switch state, some of this is not required. But the unwinder takes - struct pt_regs * as an arg so we have to build this structure - to allow unwinding switched tasks in show_state() */ - - st.q r0, ( 9*8), r9 - st.q r0, (10*8), r10 - st.q r0, (11*8), r11 - st.q r0, (12*8), r12 - st.q r0, (13*8), r13 - st.q r0, (14*8), r14 ! for unwind, want to look as though we took a trap at - ! the point where the process is left in suspended animation, i.e. current - ! fp here, not the saved one. - st.q r0, (16*8), r16 - - st.q r0, (24*8), r24 - st.q r0, (25*8), r25 - st.q r0, (26*8), r26 - st.q r0, (27*8), r27 - st.q r0, (28*8), r28 - st.q r0, (29*8), r29 - st.q r0, (30*8), r30 - st.q r0, (31*8), r31 - st.q r0, (32*8), r32 - st.q r0, (33*8), r33 - st.q r0, (34*8), r34 - st.q r0, (35*8), r35 - - st.q r0, (44*8), r44 - st.q r0, (45*8), r45 - st.q r0, (46*8), r46 - st.q r0, (47*8), r47 - st.q r0, (48*8), r48 - st.q r0, (49*8), r49 - st.q r0, (50*8), r50 - st.q r0, (51*8), r51 - st.q r0, (52*8), r52 - st.q r0, (53*8), r53 - st.q r0, (54*8), r54 - st.q r0, (55*8), r55 - st.q r0, (56*8), r56 - st.q r0, (57*8), r57 - st.q r0, (58*8), r58 - st.q r0, (59*8), r59 - - ! do this early as pta->gettr has no pipeline forwarding (=> 5 cycle latency) - ! Use a local label to avoid creating a symbol that will confuse the ! - ! backtrace - pta .Lsave_pc, tr0 - - gettr tr5, r45 - gettr tr6, r46 - gettr tr7, r47 - st.q r8, (5*8), r45 - st.q r8, (6*8), r46 - st.q r8, (7*8), r47 - - ! Now switch context - gettr tr0, r9 - st.l r3, 0, r15 ! prev->thread.sp - st.l r3, 8, r1 ! prev->thread.kregs - st.l r3, 4, r9 ! prev->thread.pc - st.q r1, 0, r9 ! save prev->thread.pc into pt_regs->pc - - ! Load PC for next task (init value or save_pc later) - ld.l r5, 4, r18 ! next->thread.pc - ! Switch stacks - ld.l r5, 0, r15 ! next->thread.sp - ptabs r18, tr0 - - ! Update current - ld.l r4, 4, r9 ! next->thread_info (2nd element of next task_struct) - putcon r9, kcr0 ! current = next->thread_info - - ! go to save_pc for a reschedule, or the initial thread.pc for a new process - blink tr0, r63 - - ! Restore (when we come back to a previously saved task) -.Lsave_pc: - addi.l r15, 32, r0 ! r0 = next's regs - addi.l r0, (63*8), r8 ! r8 = next's tr_regs - - ld.q r8, (5*8), r45 - ld.q r8, (6*8), r46 - ld.q r8, (7*8), r47 - ptabs r45, tr5 - ptabs r46, tr6 - ptabs r47, tr7 - - ld.q r0, ( 9*8), r9 - ld.q r0, (10*8), r10 - ld.q r0, (11*8), r11 - ld.q r0, (12*8), r12 - ld.q r0, (13*8), r13 - ld.q r0, (14*8), r14 - ld.q r0, (16*8), r16 - - ld.q r0, (24*8), r24 - ld.q r0, (25*8), r25 - ld.q r0, (26*8), r26 - ld.q r0, (27*8), r27 - ld.q r0, (28*8), r28 - ld.q r0, (29*8), r29 - ld.q r0, (30*8), r30 - ld.q r0, (31*8), r31 - ld.q r0, (32*8), r32 - ld.q r0, (33*8), r33 - ld.q r0, (34*8), r34 - ld.q r0, (35*8), r35 - - ld.q r0, (44*8), r44 - ld.q r0, (45*8), r45 - ld.q r0, (46*8), r46 - ld.q r0, (47*8), r47 - ld.q r0, (48*8), r48 - ld.q r0, (49*8), r49 - ld.q r0, (50*8), r50 - ld.q r0, (51*8), r51 - ld.q r0, (52*8), r52 - ld.q r0, (53*8), r53 - ld.q r0, (54*8), r54 - ld.q r0, (55*8), r55 - ld.q r0, (56*8), r56 - ld.q r0, (57*8), r57 - ld.q r0, (58*8), r58 - ld.q r0, (59*8), r59 - - ! epilogue - ld.l r15, 0, r18 - ld.l r15, 4, r14 - ptabs r18, tr0 - movi FRAME_SIZE, r0 - add r15, r0, r15 - blink tr0, r63 -__sh64_switch_to_end: -.LFE1: - .size sh64_switch_to,.LFE1-sh64_switch_to - diff -puN arch/sh64/kernel/sys_sh64.c~git-sh /dev/null --- a/arch/sh64/kernel/sys_sh64.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/sys_sh64.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * This file contains various random system calls that - * have a non-standard calling sequence on the Linux/SH5 - * platform. - * - * Mostly taken from i386 version. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REG_3 3 - -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way Unix traditionally does this, though. - */ -#ifdef NEW_PIPE_IMPLEMENTATION -asmlinkage int sys_pipe(unsigned long * fildes, - unsigned long dummy_r3, - unsigned long dummy_r4, - unsigned long dummy_r5, - unsigned long dummy_r6, - unsigned long dummy_r7, - struct pt_regs * regs) /* r8 = pt_regs forced by entry.S */ -{ - int fd[2]; - int ret; - - ret = do_pipe(fd); - if (ret == 0) - /* - *********************************************************************** - * To avoid the copy_to_user we prefer to break the ABIs convention, * - * packing the valid pair of file IDs into a single register (r3); * - * while r2 is the return code as defined by the sh5-ABIs. * - * BE CAREFUL: pipe stub, into glibc, must be aware of this solution * - *********************************************************************** - -#ifdef __LITTLE_ENDIAN__ - regs->regs[REG_3] = (((unsigned long long) fd[1]) << 32) | ((unsigned long long) fd[0]); -#else - regs->regs[REG_3] = (((unsigned long long) fd[0]) << 32) | ((unsigned long long) fd[1]); -#endif - - */ - /* although not very clever this is endianess independent */ - regs->regs[REG_3] = (unsigned long long) *((unsigned long long *) fd); - - return ret; -} - -#else -asmlinkage int 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; -} - -#endif - -/* - * To avoid cache alias, we map the shard page with same color. - */ -#define COLOUR_ALIGN(addr) (((addr)+SHMLBA-1)&~(SHMLBA-1)) - -unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, - unsigned long len, unsigned long pgoff, unsigned long flags) -{ - struct vm_area_struct *vma; - - if (flags & MAP_FIXED) { - /* We do not accept a shared mapping if it would violate - * cache aliasing constraints. - */ - if ((flags & MAP_SHARED) && (addr & (SHMLBA - 1))) - return -EINVAL; - return addr; - } - - if (len > TASK_SIZE) - return -ENOMEM; - if (!addr) - addr = TASK_UNMAPPED_BASE; - - if (flags & MAP_PRIVATE) - addr = PAGE_ALIGN(addr); - else - addr = COLOUR_ALIGN(addr); - - for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) { - /* At this point: (!vma || addr < vma->vm_end). */ - if (TASK_SIZE - len < addr) - return -ENOMEM; - if (!vma || addr + len <= vma->vm_start) - return addr; - addr = vma->vm_end; - if (!(flags & MAP_PRIVATE)) - addr = COLOUR_ALIGN(addr); - } -} - -/* common code for old and new mmaps */ -static inline long do_mmap2( - unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - int error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - 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; -} - -asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - return do_mmap2(addr, len, prot, flags, fd, pgoff); -} - -asmlinkage int old_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - int fd, unsigned long off) -{ - if (off & ~PAGE_MASK) - return -EINVAL; - return do_mmap2(addr, len, prot, flags, fd, off>>PAGE_SHIFT); -} - -/* - * sys_ipc() is the de-multiplexer for the SysV IPC calls.. - * - * This is really horribly ugly. - */ -asmlinkage int sys_ipc(uint call, int first, int second, - int third, void __user *ptr, long fifth) -{ - int version, ret; - - version = call >> 16; /* hack for backward compatibility */ - call &= 0xffff; - - if (call <= SEMCTL) - 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); - } - default: - return -EINVAL; - } - - if (call <= MSGCTL) - switch (call) { - 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); - default: - return -EINVAL; - } - if (call <= SHMCTL) - switch (call) { - 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; - 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 -EINVAL; - } - - return -EINVAL; -} - -asmlinkage int sys_uname(struct old_utsname * name) -{ - int err; - if (!name) - return -EFAULT; - down_read(&uts_sem); - err = copy_to_user(name, utsname(), sizeof (*name)); - up_read(&uts_sem); - return err?-EFAULT:0; -} - -/* - * Do a system call from kernel instead of calling sys_execve so we - * end up with proper pt_regs. - */ -int kernel_execve(const char *filename, char *const argv[], char *const envp[]) -{ - register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve); - register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename; - register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv; - register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp; - __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)" - : "=r" (__sc0) - : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) ); - __asm__ __volatile__ ("!dummy %0 %1 %2 %3" - : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory"); - return __sc0; -} diff -puN arch/sh64/kernel/syscalls.S~git-sh /dev/null --- a/arch/sh64/kernel/syscalls.S +++ /dev/null @@ -1,381 +0,0 @@ -/* - * arch/sh64/kernel/syscalls.S - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004 - 2007 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include - - .section .data, "aw" - .balign 32 - -/* - * System calls jump table - */ - .globl sys_call_table -sys_call_table: - .long sys_restart_syscall /* 0 - old "setup()" system call */ - .long sys_exit - .long sys_fork - .long sys_read - .long sys_write - .long sys_open /* 5 */ - .long sys_close - .long sys_waitpid - .long sys_creat - .long sys_link - .long sys_unlink /* 10 */ - .long sys_execve - .long sys_chdir - .long sys_time - .long sys_mknod - .long sys_chmod /* 15 */ - .long sys_lchown16 - .long sys_ni_syscall /* old break syscall holder */ - .long sys_stat - .long sys_lseek - .long sys_getpid /* 20 */ - .long sys_mount - .long sys_oldumount - .long sys_setuid16 - .long sys_getuid16 - .long sys_stime /* 25 */ - .long sh64_ptrace - .long sys_alarm - .long sys_fstat - .long sys_pause - .long sys_utime /* 30 */ - .long sys_ni_syscall /* old stty syscall holder */ - .long sys_ni_syscall /* old gtty syscall holder */ - .long sys_access - .long sys_nice - .long sys_ni_syscall /* 35 */ /* old ftime syscall holder */ - .long sys_sync - .long sys_kill - .long sys_rename - .long sys_mkdir - .long sys_rmdir /* 40 */ - .long sys_dup - .long sys_pipe - .long sys_times - .long sys_ni_syscall /* old prof syscall holder */ - .long sys_brk /* 45 */ - .long sys_setgid16 - .long sys_getgid16 - .long sys_signal - .long sys_geteuid16 - .long sys_getegid16 /* 50 */ - .long sys_acct - .long sys_umount /* recycled never used phys( */ - .long sys_ni_syscall /* old lock syscall holder */ - .long sys_ioctl - .long sys_fcntl /* 55 */ - .long sys_ni_syscall /* old mpx syscall holder */ - .long sys_setpgid - .long sys_ni_syscall /* old ulimit syscall holder */ - .long sys_ni_syscall /* sys_olduname */ - .long sys_umask /* 60 */ - .long sys_chroot - .long sys_ustat - .long sys_dup2 - .long sys_getppid - .long sys_getpgrp /* 65 */ - .long sys_setsid - .long sys_sigaction - .long sys_sgetmask - .long sys_ssetmask - .long sys_setreuid16 /* 70 */ - .long sys_setregid16 - .long sys_sigsuspend - .long sys_sigpending - .long sys_sethostname - .long sys_setrlimit /* 75 */ - .long sys_old_getrlimit - .long sys_getrusage - .long sys_gettimeofday - .long sys_settimeofday - .long sys_getgroups16 /* 80 */ - .long sys_setgroups16 - .long sys_ni_syscall /* sys_oldselect */ - .long sys_symlink - .long sys_lstat - .long sys_readlink /* 85 */ - .long sys_uselib - .long sys_swapon - .long sys_reboot - .long old_readdir - .long old_mmap /* 90 */ - .long sys_munmap - .long sys_truncate - .long sys_ftruncate - .long sys_fchmod - .long sys_fchown16 /* 95 */ - .long sys_getpriority - .long sys_setpriority - .long sys_ni_syscall /* old profil syscall holder */ - .long sys_statfs - .long sys_fstatfs /* 100 */ - .long sys_ni_syscall /* ioperm */ - .long sys_socketcall /* Obsolete implementation of socket syscall */ - .long sys_syslog - .long sys_setitimer - .long sys_getitimer /* 105 */ - .long sys_newstat - .long sys_newlstat - .long sys_newfstat - .long sys_uname - .long sys_ni_syscall /* 110 */ /* iopl */ - .long sys_vhangup - .long sys_ni_syscall /* idle */ - .long sys_ni_syscall /* vm86old */ - .long sys_wait4 - .long sys_swapoff /* 115 */ - .long sys_sysinfo - .long sys_ipc /* Obsolete ipc syscall implementation */ - .long sys_fsync - .long sys_sigreturn - .long sys_clone /* 120 */ - .long sys_setdomainname - .long sys_newuname - .long sys_ni_syscall /* sys_modify_ldt */ - .long sys_adjtimex - .long sys_mprotect /* 125 */ - .long sys_sigprocmask - .long sys_ni_syscall /* old "create_module" */ - .long sys_init_module - .long sys_delete_module - .long sys_ni_syscall /* 130: old "get_kernel_syms" */ - .long sys_quotactl - .long sys_getpgid - .long sys_fchdir - .long sys_bdflush - .long sys_sysfs /* 135 */ - .long sys_personality - .long sys_ni_syscall /* for afs_syscall */ - .long sys_setfsuid16 - .long sys_setfsgid16 - .long sys_llseek /* 140 */ - .long sys_getdents - .long sys_select - .long sys_flock - .long sys_msync - .long sys_readv /* 145 */ - .long sys_writev - .long sys_getsid - .long sys_fdatasync - .long sys_sysctl - .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 - .long sys_sched_getscheduler - .long sys_sched_yield - .long sys_sched_get_priority_max - .long sys_sched_get_priority_min /* 160 */ - .long sys_sched_rr_get_interval - .long sys_nanosleep - .long sys_mremap - .long sys_setresuid16 - .long sys_getresuid16 /* 165 */ - .long sys_ni_syscall /* vm86 */ - .long sys_ni_syscall /* old "query_module" */ - .long sys_poll - .long sys_nfsservctl - .long sys_setresgid16 /* 170 */ - .long sys_getresgid16 - .long sys_prctl - .long sys_rt_sigreturn - .long sys_rt_sigaction - .long sys_rt_sigprocmask /* 175 */ - .long sys_rt_sigpending - .long sys_rt_sigtimedwait - .long sys_rt_sigqueueinfo - .long sys_rt_sigsuspend - .long sys_pread64 /* 180 */ - .long sys_pwrite64 - .long sys_chown16 - .long sys_getcwd - .long sys_capget - .long sys_capset /* 185 */ - .long sys_sigaltstack - .long sys_sendfile - .long sys_ni_syscall /* streams1 */ - .long sys_ni_syscall /* streams2 */ - .long sys_vfork /* 190 */ - .long sys_getrlimit - .long sys_mmap2 - .long sys_truncate64 - .long sys_ftruncate64 - .long sys_stat64 /* 195 */ - .long sys_lstat64 - .long sys_fstat64 - .long sys_lchown - .long sys_getuid - .long sys_getgid /* 200 */ - .long sys_geteuid - .long sys_getegid - .long sys_setreuid - .long sys_setregid - .long sys_getgroups /* 205 */ - .long sys_setgroups - .long sys_fchown - .long sys_setresuid - .long sys_getresuid - .long sys_setresgid /* 210 */ - .long sys_getresgid - .long sys_chown - .long sys_setuid - .long sys_setgid - .long sys_setfsuid /* 215 */ - .long sys_setfsgid - .long sys_pivot_root - .long sys_mincore - .long sys_madvise - /* Broken-out socket family (maintain backwards compatibility in syscall - numbering with 2.4) */ - .long sys_socket /* 220 */ - .long sys_bind - .long sys_connect - .long sys_listen - .long sys_accept - .long sys_getsockname /* 225 */ - .long sys_getpeername - .long sys_socketpair - .long sys_send - .long sys_sendto - .long sys_recv /* 230*/ - .long sys_recvfrom - .long sys_shutdown - .long sys_setsockopt - .long sys_getsockopt - .long sys_sendmsg /* 235 */ - .long sys_recvmsg - /* Broken-out IPC family (maintain backwards compatibility in syscall - numbering with 2.4) */ - .long sys_semop - .long sys_semget - .long sys_semctl - .long sys_msgsnd /* 240 */ - .long sys_msgrcv - .long sys_msgget - .long sys_msgctl - .long sys_shmat - .long sys_shmdt /* 245 */ - .long sys_shmget - .long sys_shmctl - /* Rest of syscalls listed in 2.4 i386 unistd.h */ - .long sys_getdents64 - .long sys_fcntl64 - .long sys_ni_syscall /* 250 reserved for TUX */ - .long sys_ni_syscall /* Reserved for Security */ - .long sys_gettid - .long sys_readahead - .long sys_setxattr - .long sys_lsetxattr /* 255 */ - .long sys_fsetxattr - .long sys_getxattr - .long sys_lgetxattr - .long sys_fgetxattr - .long sys_listxattr /* 260 */ - .long sys_llistxattr - .long sys_flistxattr - .long sys_removexattr - .long sys_lremovexattr - .long sys_fremovexattr /* 265 */ - .long sys_tkill - .long sys_sendfile64 - .long sys_futex - .long sys_sched_setaffinity - .long sys_sched_getaffinity /* 270 */ - .long sys_ni_syscall - .long sys_ni_syscall - .long sys_io_setup - .long sys_io_destroy - .long sys_io_getevents /* 275 */ - .long sys_io_submit - .long sys_io_cancel - .long sys_fadvise64 - .long sys_ni_syscall - .long sys_exit_group /* 280 */ - /* Rest of new 2.6 syscalls */ - .long sys_lookup_dcookie - .long sys_epoll_create - .long sys_epoll_ctl - .long sys_epoll_wait - .long sys_remap_file_pages /* 285 */ - .long sys_set_tid_address - .long sys_timer_create - .long sys_timer_settime - .long sys_timer_gettime - .long sys_timer_getoverrun /* 290 */ - .long sys_timer_delete - .long sys_clock_settime - .long sys_clock_gettime - .long sys_clock_getres - .long sys_clock_nanosleep /* 295 */ - .long sys_statfs64 - .long sys_fstatfs64 - .long sys_tgkill - .long sys_utimes - .long sys_fadvise64_64 /* 300 */ - .long sys_ni_syscall /* Reserved for vserver */ - .long sys_ni_syscall /* Reserved for mbind */ - .long sys_ni_syscall /* get_mempolicy */ - .long sys_ni_syscall /* set_mempolicy */ - .long sys_mq_open /* 305 */ - .long sys_mq_unlink - .long sys_mq_timedsend - .long sys_mq_timedreceive - .long sys_mq_notify - .long sys_mq_getsetattr /* 310 */ - .long sys_ni_syscall /* Reserved for kexec */ - .long sys_waitid - .long sys_add_key - .long sys_request_key - .long sys_keyctl /* 315 */ - .long sys_ioprio_set - .long sys_ioprio_get - .long sys_inotify_init - .long sys_inotify_add_watch - .long sys_inotify_rm_watch /* 320 */ - .long sys_ni_syscall - .long sys_migrate_pages - .long sys_openat - .long sys_mkdirat - .long sys_mknodat /* 325 */ - .long sys_fchownat - .long sys_futimesat - .long sys_fstatat64 - .long sys_unlinkat - .long sys_renameat /* 330 */ - .long sys_linkat - .long sys_symlinkat - .long sys_readlinkat - .long sys_fchmodat - .long sys_faccessat /* 335 */ - .long sys_pselect6 - .long sys_ppoll - .long sys_unshare - .long sys_set_robust_list - .long sys_get_robust_list /* 340 */ - .long sys_splice - .long sys_sync_file_range - .long sys_tee - .long sys_vmsplice - .long sys_move_pages /* 345 */ - .long sys_getcpu - .long sys_epoll_pwait - .long sys_utimensat - .long sys_signalfd - .long sys_timerfd /* 350 */ - .long sys_eventfd - .long sys_fallocate diff -puN arch/sh64/kernel/time.c~git-sh /dev/null --- a/arch/sh64/kernel/time.c +++ /dev/null @@ -1,593 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/time.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003 Richard Curnow - * - * Original TMU/RTC code taken from sh version. - * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka - * Some code taken from i386 version. - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* required by inline __asm__ stmt. */ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#define TMU_TOCR_INIT 0x00 -#define TMU0_TCR_INIT 0x0020 -#define TMU_TSTR_INIT 1 -#define TMU_TSTR_OFF 0 - -/* RCR1 Bits */ -#define RCR1_CF 0x80 /* Carry Flag */ -#define RCR1_CIE 0x10 /* Carry Interrupt Enable */ -#define RCR1_AIE 0x08 /* Alarm Interrupt Enable */ -#define RCR1_AF 0x01 /* Alarm Flag */ - -/* RCR2 Bits */ -#define RCR2_PEF 0x80 /* PEriodic interrupt Flag */ -#define RCR2_PESMASK 0x70 /* Periodic interrupt Set */ -#define RCR2_RTCEN 0x08 /* ENable RTC */ -#define RCR2_ADJ 0x04 /* ADJustment (30-second) */ -#define RCR2_RESET 0x02 /* Reset bit */ -#define RCR2_START 0x01 /* Start bit */ - -/* Clock, Power and Reset Controller */ -#define CPRC_BLOCK_OFF 0x01010000 -#define CPRC_BASE PHYS_PERIPHERAL_BLOCK + CPRC_BLOCK_OFF - -#define FRQCR (cprc_base+0x0) -#define WTCSR (cprc_base+0x0018) -#define STBCR (cprc_base+0x0030) - -/* Time Management Unit */ -#define TMU_BLOCK_OFF 0x01020000 -#define TMU_BASE PHYS_PERIPHERAL_BLOCK + TMU_BLOCK_OFF -#define TMU0_BASE tmu_base + 0x8 + (0xc * 0x0) -#define TMU1_BASE tmu_base + 0x8 + (0xc * 0x1) -#define TMU2_BASE tmu_base + 0x8 + (0xc * 0x2) - -#define TMU_TOCR tmu_base+0x0 /* Byte access */ -#define TMU_TSTR tmu_base+0x4 /* Byte access */ - -#define TMU0_TCOR TMU0_BASE+0x0 /* Long access */ -#define TMU0_TCNT TMU0_BASE+0x4 /* Long access */ -#define TMU0_TCR TMU0_BASE+0x8 /* Word access */ - -/* Real Time Clock */ -#define RTC_BLOCK_OFF 0x01040000 -#define RTC_BASE PHYS_PERIPHERAL_BLOCK + RTC_BLOCK_OFF - -#define R64CNT rtc_base+0x00 -#define RSECCNT rtc_base+0x04 -#define RMINCNT rtc_base+0x08 -#define RHRCNT rtc_base+0x0c -#define RWKCNT rtc_base+0x10 -#define RDAYCNT rtc_base+0x14 -#define RMONCNT rtc_base+0x18 -#define RYRCNT rtc_base+0x1c /* 16bit */ -#define RSECAR rtc_base+0x20 -#define RMINAR rtc_base+0x24 -#define RHRAR rtc_base+0x28 -#define RWKAR rtc_base+0x2c -#define RDAYAR rtc_base+0x30 -#define RMONAR rtc_base+0x34 -#define RCR1 rtc_base+0x38 -#define RCR2 rtc_base+0x3c - -#define TICK_SIZE (tick_nsec / 1000) - -static unsigned long tmu_base, rtc_base; -unsigned long cprc_base; - -/* Variables to allow interpolation of time of day to resolution better than a - * jiffy. */ - -/* This is effectively protected by xtime_lock */ -static unsigned long ctc_last_interrupt; -static unsigned long long usecs_per_jiffy = 1000000/HZ; /* Approximation */ - -#define CTC_JIFFY_SCALE_SHIFT 40 - -/* 2**CTC_JIFFY_SCALE_SHIFT / ctc_ticks_per_jiffy */ -static unsigned long long scaled_recip_ctc_ticks_per_jiffy; - -/* Estimate number of microseconds that have elapsed since the last timer tick, - by scaling the delta that has occurred in the CTC register. - - WARNING WARNING WARNING : This algorithm relies on the CTC decrementing at - the CPU clock rate. If the CPU sleeps, the CTC stops counting. Bear this - in mind if enabling SLEEP_WORKS in process.c. In that case, this algorithm - probably needs to use TMU.TCNT0 instead. This will work even if the CPU is - sleeping, though will be coarser. - - FIXME : What if usecs_per_tick is moving around too much, e.g. if an adjtime - is running or if the freq or tick arguments of adjtimex are modified after - we have calibrated the scaling factor? This will result in either a jump at - the end of a tick period, or a wrap backwards at the start of the next one, - if the application is reading the time of day often enough. I think we - ought to do better than this. For this reason, usecs_per_jiffy is left - separated out in the calculation below. This allows some future hook into - the adjtime-related stuff in kernel/timer.c to remove this hazard. - -*/ - -static unsigned long usecs_since_tick(void) -{ - unsigned long long current_ctc; - long ctc_ticks_since_interrupt; - unsigned long long ull_ctc_ticks_since_interrupt; - unsigned long result; - - unsigned long long mul1_out; - unsigned long long mul1_out_high; - unsigned long long mul2_out_low, mul2_out_high; - - /* Read CTC register */ - asm ("getcon cr62, %0" : "=r" (current_ctc)); - /* Note, the CTC counts down on each CPU clock, not up. - Note(2), use long type to get correct wraparound arithmetic when - the counter crosses zero. */ - ctc_ticks_since_interrupt = (long) ctc_last_interrupt - (long) current_ctc; - ull_ctc_ticks_since_interrupt = (unsigned long long) ctc_ticks_since_interrupt; - - /* Inline assembly to do 32x32x32->64 multiplier */ - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul1_out) : - "r" (ull_ctc_ticks_since_interrupt), "r" (usecs_per_jiffy)); - - mul1_out_high = mul1_out >> 32; - - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul2_out_low) : - "r" (mul1_out), "r" (scaled_recip_ctc_ticks_per_jiffy)); - -#if 1 - asm volatile ("mulu.l %1, %2, %0" : - "=r" (mul2_out_high) : - "r" (mul1_out_high), "r" (scaled_recip_ctc_ticks_per_jiffy)); -#endif - - result = (unsigned long) (((mul2_out_high << 32) + mul2_out_low) >> CTC_JIFFY_SCALE_SHIFT); - - return result; -} - -void do_gettimeofday(struct timeval *tv) -{ - unsigned long flags; - unsigned long seq; - unsigned long usec, sec; - - do { - seq = read_seqbegin_irqsave(&xtime_lock, flags); - usec = usecs_since_tick(); - sec = xtime.tv_sec; - usec += xtime.tv_nsec / 1000; - } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); - - while (usec >= 1000000) { - usec -= 1000000; - sec++; - } - - tv->tv_sec = sec; - tv->tv_usec = usec; -} - -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 -= 1000 * usecs_since_tick(); - - 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); - -static int set_rtc_time(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - - ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ - - cmos_minutes = ctrl_inb(RMINCNT); - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - ctrl_outb(real_seconds, RSECCNT); - ctrl_outb(real_minutes, RMINCNT); - } else { - printk(KERN_WARNING - "set_rtc_time: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ - - return retval; -} - -/* last time the RTC clock got updated */ -static long last_rtc_update = 0; - -/* - * timer_interrupt() needs to keep up the real-time clock, - * as well as call the "do_timer()" routine every clocktick - */ -static inline void do_timer_interrupt(void) -{ - unsigned long long current_ctc; - asm ("getcon cr62, %0" : "=r" (current_ctc)); - ctc_last_interrupt = (unsigned long) current_ctc; - - do_timer(1); -#ifndef CONFIG_SMP - update_process_times(user_mode(get_irq_regs())); -#endif - if (current->pid) - profile_tick(CPU_PROFILING); - -#ifdef CONFIG_HEARTBEAT - { - extern void heartbeat(void); - - heartbeat(); - } -#endif - - /* - * If we have an externally synchronized Linux clock, then update - * RTC 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_time(xtime.tv_sec) == 0) - last_rtc_update = xtime.tv_sec; - else - last_rtc_update = xtime.tv_sec - 600; /* do it again in 60 s */ - } -} - -/* - * This is the same as the above, except we _also_ save the current - * Time Stamp Counter value at the time of the timer interrupt, so that - * we later on can estimate the time of day more exactly. - */ -static irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - unsigned long timer_status; - - /* Clear UNF bit */ - timer_status = ctrl_inw(TMU0_TCR); - timer_status &= ~0x100; - ctrl_outw(timer_status, TMU0_TCR); - - /* - * 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_lock(&xtime_lock); - do_timer_interrupt(); - write_unlock(&xtime_lock); - - return IRQ_HANDLED; -} - -static unsigned long get_rtc_time(void) -{ - unsigned int sec, min, hr, wk, day, mon, yr, yr100; - - again: - do { - ctrl_outb(0, RCR1); /* Clear CF-bit */ - sec = ctrl_inb(RSECCNT); - min = ctrl_inb(RMINCNT); - hr = ctrl_inb(RHRCNT); - wk = ctrl_inb(RWKCNT); - day = ctrl_inb(RDAYCNT); - mon = ctrl_inb(RMONCNT); - yr = ctrl_inw(RYRCNT); - yr100 = (yr >> 8); - yr &= 0xff; - } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); - - BCD_TO_BIN(yr100); - BCD_TO_BIN(yr); - BCD_TO_BIN(mon); - BCD_TO_BIN(day); - BCD_TO_BIN(hr); - BCD_TO_BIN(min); - BCD_TO_BIN(sec); - - if (yr > 99 || mon < 1 || mon > 12 || day > 31 || day < 1 || - hr > 23 || min > 59 || sec > 59) { - printk(KERN_ERR - "SH RTC: invalid value, resetting to 1 Jan 2000\n"); - ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ - ctrl_outb(0, RSECCNT); - ctrl_outb(0, RMINCNT); - ctrl_outb(0, RHRCNT); - ctrl_outb(6, RWKCNT); - ctrl_outb(1, RDAYCNT); - ctrl_outb(1, RMONCNT); - ctrl_outw(0x2000, RYRCNT); - ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start */ - goto again; - } - - return mktime(yr100 * 100 + yr, mon, day, hr, min, sec); -} - -static __init unsigned int get_cpu_hz(void) -{ - unsigned int count; - unsigned long __dummy; - unsigned long ctc_val_init, ctc_val; - - /* - ** Regardless the toolchain, force the compiler to use the - ** arbitrary register r3 as a clock tick counter. - ** NOTE: r3 must be in accordance with sh64_rtc_interrupt() - */ - register unsigned long long __rtc_irq_flag __asm__ ("r3"); - - local_irq_enable(); - do {} while (ctrl_inb(R64CNT) != 0); - ctrl_outb(RCR1_CIE, RCR1); /* Enable carry interrupt */ - - /* - * r3 is arbitrary. CDC does not support "=z". - */ - ctc_val_init = 0xffffffff; - ctc_val = ctc_val_init; - - asm volatile("gettr tr0, %1\n\t" - "putcon %0, " __CTC "\n\t" - "and %2, r63, %2\n\t" - "pta $+4, tr0\n\t" - "beq/l %2, r63, tr0\n\t" - "ptabs %1, tr0\n\t" - "getcon " __CTC ", %0\n\t" - : "=r"(ctc_val), "=r" (__dummy), "=r" (__rtc_irq_flag) - : "0" (0)); - local_irq_disable(); - /* - * SH-3: - * CPU clock = 4 stages * loop - * tst rm,rm if id ex - * bt/s 1b if id ex - * add #1,rd if id ex - * (if) pipe line stole - * tst rm,rm if id ex - * .... - * - * - * SH-4: - * CPU clock = 6 stages * loop - * I don't know why. - * .... - * - * SH-5: - * Use CTC register to count. This approach returns the right value - * even if the I-cache is disabled (e.g. whilst debugging.) - * - */ - - count = ctc_val_init - ctc_val; /* CTC counts down */ - -#if defined (CONFIG_SH_SIMULATOR) - /* - * Let's pretend we are a 5MHz SH-5 to avoid a too - * little timer interval. Also to keep delay - * calibration within a reasonable time. - */ - return 5000000; -#else - /* - * This really is count by the number of clock cycles - * by the ratio between a complete R64CNT - * wrap-around (128) and CUI interrupt being raised (64). - */ - return count*2; -#endif -} - -static irqreturn_t sh64_rtc_interrupt(int irq, void *dev_id) -{ - struct pt_regs *regs = get_irq_regs(); - - ctrl_outb(0, RCR1); /* Disable Carry Interrupts */ - regs->regs[3] = 1; /* Using r3 */ - - return IRQ_HANDLED; -} - -static struct irqaction irq0 = { - .handler = timer_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "timer", -}; -static struct irqaction irq1 = { - .handler = sh64_rtc_interrupt, - .flags = IRQF_DISABLED, - .mask = CPU_MASK_NONE, - .name = "rtc", -}; - -void __init time_init(void) -{ - unsigned int cpu_clock, master_clock, bus_clock, module_clock; - unsigned long interval; - unsigned long frqcr, ifc, pfc; - static int ifc_table[] = { 2, 4, 6, 8, 10, 12, 16, 24 }; -#define bfc_table ifc_table /* Same */ -#define pfc_table ifc_table /* Same */ - - tmu_base = onchip_remap(TMU_BASE, 1024, "TMU"); - if (!tmu_base) { - panic("Unable to remap TMU\n"); - } - - rtc_base = onchip_remap(RTC_BASE, 1024, "RTC"); - if (!rtc_base) { - panic("Unable to remap RTC\n"); - } - - cprc_base = onchip_remap(CPRC_BASE, 1024, "CPRC"); - if (!cprc_base) { - panic("Unable to remap CPRC\n"); - } - - xtime.tv_sec = get_rtc_time(); - xtime.tv_nsec = 0; - - setup_irq(TIMER_IRQ, &irq0); - setup_irq(RTC_IRQ, &irq1); - - /* Check how fast it is.. */ - cpu_clock = get_cpu_hz(); - - /* Note careful order of operations to maintain reasonable precision and avoid overflow. */ - scaled_recip_ctc_ticks_per_jiffy = ((1ULL << CTC_JIFFY_SCALE_SHIFT) / (unsigned long long)(cpu_clock / HZ)); - - disable_irq(RTC_IRQ); - - printk("CPU clock: %d.%02dMHz\n", - (cpu_clock / 1000000), (cpu_clock % 1000000)/10000); - { - unsigned short bfc; - frqcr = ctrl_inl(FRQCR); - ifc = ifc_table[(frqcr>> 6) & 0x0007]; - bfc = bfc_table[(frqcr>> 3) & 0x0007]; - pfc = pfc_table[(frqcr>> 12) & 0x0007]; - master_clock = cpu_clock * ifc; - bus_clock = master_clock/bfc; - } - - printk("Bus clock: %d.%02dMHz\n", - (bus_clock/1000000), (bus_clock % 1000000)/10000); - module_clock = master_clock/pfc; - printk("Module clock: %d.%02dMHz\n", - (module_clock/1000000), (module_clock % 1000000)/10000); - interval = (module_clock/(HZ*4)); - - printk("Interval = %ld\n", interval); - - current_cpu_data.cpu_clock = cpu_clock; - current_cpu_data.master_clock = master_clock; - current_cpu_data.bus_clock = bus_clock; - current_cpu_data.module_clock = module_clock; - - /* Start TMU0 */ - ctrl_outb(TMU_TSTR_OFF, TMU_TSTR); - ctrl_outb(TMU_TOCR_INIT, TMU_TOCR); - ctrl_outw(TMU0_TCR_INIT, TMU0_TCR); - ctrl_outl(interval, TMU0_TCOR); - ctrl_outl(interval, TMU0_TCNT); - ctrl_outb(TMU_TSTR_INIT, TMU_TSTR); -} - -void enter_deep_standby(void) -{ - /* Disable watchdog timer */ - ctrl_outl(0xa5000000, WTCSR); - /* Configure deep standby on sleep */ - ctrl_outl(0x03, STBCR); - -#ifdef CONFIG_SH_ALPHANUMERIC - { - extern void mach_alphanum(int position, unsigned char value); - extern void mach_alphanum_brightness(int setting); - char halted[] = "Halted. "; - int i; - mach_alphanum_brightness(6); /* dimmest setting above off */ - for (i=0; i<8; i++) { - mach_alphanum(i, halted[i]); - } - asm __volatile__ ("synco"); - } -#endif - - asm __volatile__ ("sleep"); - asm __volatile__ ("synci"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - panic("Unexpected wakeup!\n"); -} diff -puN arch/sh64/kernel/traps.c~git-sh /dev/null --- a/arch/sh64/kernel/traps.c +++ /dev/null @@ -1,982 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/traps.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - */ - -/* - * 'Traps.c' handles hardware traps and faults after we have saved some - * state in 'entry.S'. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#undef DEBUG_EXCEPTION -#ifdef DEBUG_EXCEPTION -/* implemented in ../lib/dbg.c */ -extern void show_excp_regs(char *fname, int trapnr, int signr, - struct pt_regs *regs); -#else -#define show_excp_regs(a, b, c, d) -#endif - -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk); - -#define DO_ERROR(trapnr, signr, str, name, tsk) \ -asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \ -{ \ - do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \ -} - -spinlock_t die_lock; - -void die(const char * str, struct pt_regs * regs, long err) -{ - console_verbose(); - spin_lock_irq(&die_lock); - printk("%s: %lx\n", str, (err & 0xffffff)); - show_regs(regs); - spin_unlock_irq(&die_lock); - do_exit(SIGSEGV); -} - -static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) - die(str, regs, err); -} - -static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err) -{ - if (!user_mode(regs)) { - const struct exception_table_entry *fixup; - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - die(str, regs, err); - } -} - -DO_ERROR(13, SIGILL, "illegal slot instruction", illegal_slot_inst, current) -DO_ERROR(87, SIGSEGV, "address error (exec)", address_error_exec, current) - - -/* Implement misaligned load/store handling for kernel (and optionally for user - mode too). Limitation : only SHmedia mode code is handled - there is no - handling at all for misaligned accesses occurring in SHcompact code yet. */ - -static int misaligned_fixup(struct pt_regs *regs); - -asmlinkage void do_address_error_load(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(7, SIGSEGV, "address error(load)", - "do_address_error_load", - error_code, regs, current); - } - return; -} - -asmlinkage void do_address_error_store(unsigned long error_code, struct pt_regs *regs) -{ - if (misaligned_fixup(regs) < 0) { - do_unhandled_exception(8, SIGSEGV, "address error(store)", - "do_address_error_store", - error_code, regs, current); - } - return; -} - -#if defined(CONFIG_SH64_ID2815_WORKAROUND) - -#define OPCODE_INVALID 0 -#define OPCODE_USER_VALID 1 -#define OPCODE_PRIV_VALID 2 - -/* getcon/putcon - requires checking which control register is referenced. */ -#define OPCODE_CTRL_REG 3 - -/* Table of valid opcodes for SHmedia mode. - Form a 10-bit value by concatenating the major/minor opcodes i.e. - opcode[31:26,20:16]. The 6 MSBs of this value index into the following - array. The 4 LSBs select the bit-pair in the entry (bits 1:0 correspond to - LSBs==4'b0000 etc). */ -static unsigned long shmedia_opcode_table[64] = { - 0x55554044,0x54445055,0x15141514,0x14541414,0x00000000,0x10001000,0x01110055,0x04050015, - 0x00000444,0xc0000000,0x44545515,0x40405555,0x55550015,0x10005555,0x55555505,0x04050000, - 0x00000555,0x00000404,0x00040445,0x15151414,0x00000000,0x00000000,0x00000000,0x00000000, - 0x00000055,0x40404444,0x00000404,0xc0009495,0x00000000,0x00000000,0x00000000,0x00000000, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x80005050,0x04005055,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555,0x55555555, - 0x81055554,0x00000404,0x55555555,0x55555555,0x00000000,0x00000000,0x00000000,0x00000000 -}; - -void do_reserved_inst(unsigned long error_code, struct pt_regs *regs) -{ - /* Workaround SH5-101 cut2 silicon defect #2815 : - in some situations, inter-mode branches from SHcompact -> SHmedia - which should take ITLBMISS or EXECPROT exceptions at the target - falsely take RESINST at the target instead. */ - - unsigned long opcode = 0x6ff4fff0; /* guaranteed reserved opcode */ - unsigned long pc, aligned_pc; - int get_user_error; - int trapnr = 12; - int signr = SIGILL; - char *exception_name = "reserved_instruction"; - - pc = regs->pc; - if ((pc & 3) == 1) { - /* SHmedia : check for defect. This requires executable vmas - to be readable too. */ - aligned_pc = pc & ~3; - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { - get_user_error = -EFAULT; - } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); - } - if (get_user_error >= 0) { - unsigned long index, shift; - unsigned long major, minor, combined; - unsigned long reserved_field; - reserved_field = opcode & 0xf; /* These bits are currently reserved as zero in all valid opcodes */ - major = (opcode >> 26) & 0x3f; - minor = (opcode >> 16) & 0xf; - combined = (major << 4) | minor; - index = major; - shift = minor << 1; - if (reserved_field == 0) { - int opcode_state = (shmedia_opcode_table[index] >> shift) & 0x3; - switch (opcode_state) { - case OPCODE_INVALID: - /* Trap. */ - break; - case OPCODE_USER_VALID: - /* Restart the instruction : the branch to the instruction will now be from an RTE - not from SHcompact so the silicon defect won't be triggered. */ - return; - case OPCODE_PRIV_VALID: - if (!user_mode(regs)) { - /* Should only ever get here if a module has - SHcompact code inside it. If so, the same fix up is needed. */ - return; /* same reason */ - } - /* Otherwise, user mode trying to execute a privileged instruction - - fall through to trap. */ - break; - case OPCODE_CTRL_REG: - /* If in privileged mode, return as above. */ - if (!user_mode(regs)) return; - /* In user mode ... */ - if (combined == 0x9f) { /* GETCON */ - unsigned long regno = (opcode >> 20) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else if (combined == 0x1bf) { /* PUTCON */ - unsigned long regno = (opcode >> 4) & 0x3f; - if (regno >= 62) { - return; - } - /* Otherwise, reserved or privileged control register, => trap */ - } else { - /* Trap */ - } - break; - default: - /* Fall through to trap. */ - break; - } - } - /* fall through to normal resinst processing */ - } else { - /* Error trying to read opcode. This typically means a - real fault, not a RESINST any more. So change the - codes. */ - trapnr = 87; - exception_name = "address error (exec)"; - signr = SIGSEGV; - } - } - - do_unhandled_exception(trapnr, signr, exception_name, "do_reserved_inst", error_code, regs, current); -} - -#else /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* If the workaround isn't needed, this is just a straightforward reserved - instruction */ -DO_ERROR(12, SIGILL, "reserved instruction", reserved_inst, current) - -#endif /* CONFIG_SH64_ID2815_WORKAROUND */ - -/* Called with interrupts disabled */ -asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs) -{ - PLS(); - show_excp_regs(__FUNCTION__, -1, -1, regs); - die_if_kernel("exception", regs, ex); -} - -int do_unknown_trapa(unsigned long scId, struct pt_regs *regs) -{ - /* Syscall debug */ - printk("System call ID error: [0x1#args:8 #syscall:16 0x%lx]\n", scId); - - die_if_kernel("unknown trapa", regs, scId); - - return -ENOSYS; -} - -void show_stack(struct task_struct *tsk, unsigned long *sp) -{ -#ifdef CONFIG_KALLSYMS - extern void sh64_unwind(struct pt_regs *regs); - struct pt_regs *regs; - - regs = tsk ? tsk->thread.kregs : NULL; - - sh64_unwind(regs); -#else - printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n"); -#endif -} - -void show_task(unsigned long *sp) -{ - show_stack(NULL, sp); -} - -void dump_stack(void) -{ - show_task(NULL); -} -/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */ -EXPORT_SYMBOL(dump_stack); - -static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name, - unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk) -{ - show_excp_regs(fn_name, trapnr, signr, regs); - tsk->thread.error_code = error_code; - tsk->thread.trap_no = trapnr; - - if (user_mode(regs)) - force_sig(signr, tsk); - - die_if_no_fixup(str, regs, error_code); -} - -static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode) -{ - int get_user_error; - unsigned long aligned_pc; - unsigned long opcode; - - if ((pc & 3) == 1) { - /* SHmedia */ - aligned_pc = pc & ~3; - if (from_user_mode) { - if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) { - get_user_error = -EFAULT; - } else { - get_user_error = __get_user(opcode, (unsigned long *)aligned_pc); - *result_opcode = opcode; - } - return get_user_error; - } else { - /* If the fault was in the kernel, we can either read - * this directly, or if not, we fault. - */ - *result_opcode = *(unsigned long *) aligned_pc; - return 0; - } - } else if ((pc & 1) == 0) { - /* SHcompact */ - /* TODO : provide handling for this. We don't really support - user-mode SHcompact yet, and for a kernel fault, this would - have to come from a module built for SHcompact. */ - return -EFAULT; - } else { - /* misaligned */ - return -EFAULT; - } -} - -static int address_is_sign_extended(__u64 a) -{ - __u64 b; -#if (NEFF == 32) - b = (__u64)(__s64)(__s32)(a & 0xffffffffUL); - return (b == a) ? 1 : 0; -#else -#error "Sign extend check only works for NEFF==32" -#endif -} - -static int generate_and_check_address(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - __u64 *address) -{ - /* return -1 for fault, 0 for OK */ - - __u64 base_address, addr; - int basereg; - - basereg = (opcode >> 20) & 0x3f; - base_address = regs->regs[basereg]; - if (displacement_not_indexed) { - __s64 displacement; - displacement = (opcode >> 10) & 0x3ff; - displacement = ((displacement << 54) >> 54); /* sign extend */ - addr = (__u64)((__s64)base_address + (displacement << width_shift)); - } else { - __u64 offset; - int offsetreg; - offsetreg = (opcode >> 10) & 0x3f; - offset = regs->regs[offsetreg]; - addr = base_address + offset; - } - - /* Check sign extended */ - if (!address_is_sign_extended(addr)) { - return -1; - } - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - /* Check accessible. For misaligned access in the kernel, assume the - address is always accessible (and if not, just fault when the - load/store gets done.) */ - if (user_mode(regs)) { - if (addr >= TASK_SIZE) { - return -1; - } - /* Do access_ok check later - it depends on whether it's a load or a store. */ - } -#endif - - *address = addr; - return 0; -} - -/* Default value as for sh */ -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) -static int user_mode_unaligned_fixup_count = 10; -static int user_mode_unaligned_fixup_enable = 1; -#endif - -static int kernel_mode_unaligned_fixup_count = 32; - -static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result) -{ - unsigned short x; - unsigned char *p, *q; - p = (unsigned char *) (int) address; - q = (unsigned char *) &x; - q[0] = p[0]; - q[1] = p[1]; - - if (do_sign_extend) { - *result = (__u64)(__s64) *(short *) &x; - } else { - *result = (__u64) x; - } -} - -static void misaligned_kernel_word_store(__u64 address, __u64 value) -{ - unsigned short x; - unsigned char *p, *q; - p = (unsigned char *) (int) address; - q = (unsigned char *) &x; - - x = (__u16) value; - p[0] = q[0]; - p[1] = q[1]; -} - -static int misaligned_load(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_sign_extend) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int destreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - destreg = (opcode >> 4) & 0x3f; -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs)) { - __u64 buffer; - - if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL< 0) { - return -1; /* fault */ - } - switch (width_shift) { - case 1: - if (do_sign_extend) { - regs->regs[destreg] = (__u64)(__s64) *(__s16 *) &buffer; - } else { - regs->regs[destreg] = (__u64) *(__u16 *) &buffer; - } - break; - case 2: - regs->regs[destreg] = (__u64)(__s64) *(__s32 *) &buffer; - break; - case 3: - regs->regs[destreg] = buffer; - break; - default: - printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } else -#endif - { - /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ - __u64 lo, hi; - - switch (width_shift) { - case 1: - misaligned_kernel_word_load(address, do_sign_extend, ®s->regs[destreg]); - break; - case 2: - asm ("ldlo.l %1, 0, %0" : "=r" (lo) : "r" (address)); - asm ("ldhi.l %1, 3, %0" : "=r" (hi) : "r" (address)); - regs->regs[destreg] = lo | hi; - break; - case 3: - asm ("ldlo.q %1, 0, %0" : "=r" (lo) : "r" (address)); - asm ("ldhi.q %1, 7, %0" : "=r" (hi) : "r" (address)); - regs->regs[destreg] = lo | hi; - break; - - default: - printk("Unexpected width_shift %d in misaligned_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } - - return 0; - -} - -static int misaligned_store(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int srcreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - srcreg = (opcode >> 4) & 0x3f; -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs)) { - __u64 buffer; - - if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<regs[srcreg]; - break; - case 2: - *(__u32 *) &buffer = (__u32) regs->regs[srcreg]; - break; - case 3: - buffer = regs->regs[srcreg]; - break; - default: - printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - - if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - } else -#endif - { - /* kernel mode - we can take short cuts since if we fault, it's a genuine bug */ - __u64 val = regs->regs[srcreg]; - - switch (width_shift) { - case 1: - misaligned_kernel_word_store(address, val); - break; - case 2: - asm ("stlo.l %1, 0, %0" : : "r" (val), "r" (address)); - asm ("sthi.l %1, 3, %0" : : "r" (val), "r" (address)); - break; - case 3: - asm ("stlo.q %1, 0, %0" : : "r" (val), "r" (address)); - asm ("sthi.q %1, 7, %0" : : "r" (val), "r" (address)); - break; - - default: - printk("Unexpected width_shift %d in misaligned_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - } - - return 0; - -} - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) -/* Never need to fix up misaligned FPU accesses within the kernel since that's a real - error. */ -static int misaligned_fpu_load(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_paired_load) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int destreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - destreg = (opcode >> 4) & 0x3f; - if (user_mode(regs)) { - __u64 buffer; - __u32 buflo, bufhi; - - if (!access_ok(VERIFY_READ, (unsigned long) address, 1UL< 0) { - return -1; /* fault */ - } - /* 'current' may be the current owner of the FPU state, so - context switch the registers into memory so they can be - indexed by register number. */ - if (last_task_used_math == current) { - grab_fpu(); - fpsave(¤t->thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - buflo = *(__u32*) &buffer; - bufhi = *(1 + (__u32*) &buffer); - - switch (width_shift) { - case 2: - current->thread.fpu.hard.fp_regs[destreg] = buflo; - break; - case 3: - if (do_paired_load) { - current->thread.fpu.hard.fp_regs[destreg] = buflo; - current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; - } else { -#if defined(CONFIG_LITTLE_ENDIAN) - current->thread.fpu.hard.fp_regs[destreg] = bufhi; - current->thread.fpu.hard.fp_regs[destreg+1] = buflo; -#else - current->thread.fpu.hard.fp_regs[destreg] = buflo; - current->thread.fpu.hard.fp_regs[destreg+1] = bufhi; -#endif - } - break; - default: - printk("Unexpected width_shift %d in misaligned_fpu_load, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - return 0; - } else { - die ("Misaligned FPU load inside kernel", regs, 0); - return -1; - } - - -} - -static int misaligned_fpu_store(struct pt_regs *regs, - __u32 opcode, - int displacement_not_indexed, - int width_shift, - int do_paired_load) -{ - /* Return -1 for a fault, 0 for OK */ - int error; - int srcreg; - __u64 address; - - error = generate_and_check_address(regs, opcode, - displacement_not_indexed, width_shift, &address); - if (error < 0) { - return error; - } - - srcreg = (opcode >> 4) & 0x3f; - if (user_mode(regs)) { - __u64 buffer; - /* Initialise these to NaNs. */ - __u32 buflo=0xffffffffUL, bufhi=0xffffffffUL; - - if (!access_ok(VERIFY_WRITE, (unsigned long) address, 1UL<thread.fpu.hard); - release_fpu(); - last_task_used_math = NULL; - regs->sr |= SR_FD; - } - - switch (width_shift) { - case 2: - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - break; - case 3: - if (do_paired_load) { - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; - } else { -#if defined(CONFIG_LITTLE_ENDIAN) - bufhi = current->thread.fpu.hard.fp_regs[srcreg]; - buflo = current->thread.fpu.hard.fp_regs[srcreg+1]; -#else - buflo = current->thread.fpu.hard.fp_regs[srcreg]; - bufhi = current->thread.fpu.hard.fp_regs[srcreg+1]; -#endif - } - break; - default: - printk("Unexpected width_shift %d in misaligned_fpu_store, PC=%08lx\n", - width_shift, (unsigned long) regs->pc); - break; - } - - *(__u32*) &buffer = buflo; - *(1 + (__u32*) &buffer) = bufhi; - if (__copy_user((void *)(int)address, &buffer, (1 << width_shift)) > 0) { - return -1; /* fault */ - } - return 0; - } else { - die ("Misaligned FPU load inside kernel", regs, 0); - return -1; - } -} -#endif - -static int misaligned_fixup(struct pt_regs *regs) -{ - unsigned long opcode; - int error; - int major, minor; - -#if !defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - /* Never fixup user mode misaligned accesses without this option enabled. */ - return -1; -#else - if (!user_mode_unaligned_fixup_enable) return -1; -#endif - - error = read_opcode(regs->pc, &opcode, user_mode(regs)); - if (error < 0) { - return error; - } - major = (opcode >> 26) & 0x3f; - minor = (opcode >> 16) & 0xf; - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) { - --user_mode_unaligned_fixup_count; - /* Only do 'count' worth of these reports, to remove a potential DoS against syslog */ - printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } else -#endif - if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) { - --kernel_mode_unaligned_fixup_count; - if (in_interrupt()) { - printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n", - (__u32)regs->pc, opcode); - } else { - printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n", - current->comm, task_pid_nr(current), (__u32)regs->pc, opcode); - } - } - - - switch (major) { - case (0x84>>2): /* LD.W */ - error = misaligned_load(regs, opcode, 1, 1, 1); - break; - case (0xb0>>2): /* LD.UW */ - error = misaligned_load(regs, opcode, 1, 1, 0); - break; - case (0x88>>2): /* LD.L */ - error = misaligned_load(regs, opcode, 1, 2, 1); - break; - case (0x8c>>2): /* LD.Q */ - error = misaligned_load(regs, opcode, 1, 3, 0); - break; - - case (0xa4>>2): /* ST.W */ - error = misaligned_store(regs, opcode, 1, 1); - break; - case (0xa8>>2): /* ST.L */ - error = misaligned_store(regs, opcode, 1, 2); - break; - case (0xac>>2): /* ST.Q */ - error = misaligned_store(regs, opcode, 1, 3); - break; - - case (0x40>>2): /* indexed loads */ - switch (minor) { - case 0x1: /* LDX.W */ - error = misaligned_load(regs, opcode, 0, 1, 1); - break; - case 0x5: /* LDX.UW */ - error = misaligned_load(regs, opcode, 0, 1, 0); - break; - case 0x2: /* LDX.L */ - error = misaligned_load(regs, opcode, 0, 2, 1); - break; - case 0x3: /* LDX.Q */ - error = misaligned_load(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; - - case (0x60>>2): /* indexed stores */ - switch (minor) { - case 0x1: /* STX.W */ - error = misaligned_store(regs, opcode, 0, 1); - break; - case 0x2: /* STX.L */ - error = misaligned_store(regs, opcode, 0, 2); - break; - case 0x3: /* STX.Q */ - error = misaligned_store(regs, opcode, 0, 3); - break; - default: - error = -1; - break; - } - break; - -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - case (0x94>>2): /* FLD.S */ - error = misaligned_fpu_load(regs, opcode, 1, 2, 0); - break; - case (0x98>>2): /* FLD.P */ - error = misaligned_fpu_load(regs, opcode, 1, 3, 1); - break; - case (0x9c>>2): /* FLD.D */ - error = misaligned_fpu_load(regs, opcode, 1, 3, 0); - break; - case (0x1c>>2): /* floating indexed loads */ - switch (minor) { - case 0x8: /* FLDX.S */ - error = misaligned_fpu_load(regs, opcode, 0, 2, 0); - break; - case 0xd: /* FLDX.P */ - error = misaligned_fpu_load(regs, opcode, 0, 3, 1); - break; - case 0x9: /* FLDX.D */ - error = misaligned_fpu_load(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; - case (0xb4>>2): /* FLD.S */ - error = misaligned_fpu_store(regs, opcode, 1, 2, 0); - break; - case (0xb8>>2): /* FLD.P */ - error = misaligned_fpu_store(regs, opcode, 1, 3, 1); - break; - case (0xbc>>2): /* FLD.D */ - error = misaligned_fpu_store(regs, opcode, 1, 3, 0); - break; - case (0x3c>>2): /* floating indexed stores */ - switch (minor) { - case 0x8: /* FSTX.S */ - error = misaligned_fpu_store(regs, opcode, 0, 2, 0); - break; - case 0xd: /* FSTX.P */ - error = misaligned_fpu_store(regs, opcode, 0, 3, 1); - break; - case 0x9: /* FSTX.D */ - error = misaligned_fpu_store(regs, opcode, 0, 3, 0); - break; - default: - error = -1; - break; - } - break; -#endif - - default: - /* Fault */ - error = -1; - break; - } - - if (error < 0) { - return error; - } else { - regs->pc += 4; /* Skip the instruction that's just been emulated */ - return 0; - } - -} - -static ctl_table unaligned_table[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "kernel_reports", - .data = &kernel_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, -#if defined(CONFIG_SH64_USER_MISALIGNED_FIXUP) - { - .ctl_name = CTL_UNNUMBERED, - .procname = "user_reports", - .data = &user_mode_unaligned_fixup_count, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "user_enable", - .data = &user_mode_unaligned_fixup_enable, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec}, -#endif - {} -}; - -static ctl_table unaligned_root[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "unaligned_fixup", - .mode = 0555, - unaligned_table - }, - {} -}; - -static ctl_table sh64_root[] = { - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sh64", - .mode = 0555, - .child = unaligned_root - }, - {} -}; -static struct ctl_table_header *sysctl_header; -static int __init init_sysctl(void) -{ - sysctl_header = register_sysctl_table(sh64_root); - return 0; -} - -__initcall(init_sysctl); - - -asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs) -{ - u64 peek_real_address_q(u64 addr); - u64 poke_real_address_q(u64 addr, u64 val); - unsigned long long DM_EXP_CAUSE_PHY = 0x0c100010; - unsigned long long exp_cause; - /* It's not worth ioremapping the debug module registers for the amount - of access we make to them - just go direct to their physical - addresses. */ - exp_cause = peek_real_address_q(DM_EXP_CAUSE_PHY); - if (exp_cause & ~4) { - printk("DM.EXP_CAUSE had unexpected bits set (=%08lx)\n", - (unsigned long)(exp_cause & 0xffffffff)); - } - show_state(); - /* Clear all DEBUGINT causes */ - poke_real_address_q(DM_EXP_CAUSE_PHY, 0x0); -} diff -puN arch/sh64/kernel/unwind.c~git-sh /dev/null --- a/arch/sh64/kernel/unwind.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * arch/sh64/kernel/unwind.c - * - * Copyright (C) 2004 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -static u8 regcache[63]; - -/* - * Finding the previous stack frame isn't horribly straightforward as it is - * on some other platforms. In the sh64 case, we don't have "linked" stack - * frames, so we need to do a bit of work to determine the previous frame, - * and in turn, the previous r14/r18 pair. - * - * There are generally a few cases which determine where we can find out - * the r14/r18 values. In the general case, this can be determined by poking - * around the prologue of the symbol PC is in (note that we absolutely must - * have frame pointer support as well as the kernel symbol table mapped, - * otherwise we can't even get this far). - * - * In other cases, such as the interrupt/exception path, we can poke around - * the sp/fp. - * - * Notably, this entire approach is somewhat error prone, and in the event - * that the previous frame cannot be determined, that's all we can do. - * Either way, this still leaves us with a more correct backtrace then what - * we would be able to come up with by walking the stack (which is garbage - * for anything beyond the first frame). - * -- PFM. - */ -static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, - unsigned long *pprev_fp, unsigned long *pprev_pc, - struct pt_regs *regs) -{ - const char *sym; - char namebuf[128]; - unsigned long offset; - unsigned long prologue = 0; - unsigned long fp_displacement = 0; - unsigned long fp_prev = 0; - unsigned long offset_r14 = 0, offset_r18 = 0; - int i, found_prologue_end = 0; - - sym = kallsyms_lookup(pc, NULL, &offset, NULL, namebuf); - if (!sym) - return -EINVAL; - - prologue = pc - offset; - if (!prologue) - return -EINVAL; - - /* Validate fp, to avoid risk of dereferencing a bad pointer later. - Assume 128Mb since that's the amount of RAM on a Cayman. Modify - when there is an SH-5 board with more. */ - if ((fp < (unsigned long) phys_to_virt(__MEMORY_START)) || - (fp >= (unsigned long)(phys_to_virt(__MEMORY_START)) + 128*1024*1024) || - ((fp & 7) != 0)) { - return -EINVAL; - } - - /* - * Depth to walk, depth is completely arbitrary. - */ - for (i = 0; i < 100; i++, prologue += sizeof(unsigned long)) { - unsigned long op; - u8 major, minor; - u8 src, dest, disp; - - op = *(unsigned long *)prologue; - - major = (op >> 26) & 0x3f; - src = (op >> 20) & 0x3f; - minor = (op >> 16) & 0xf; - disp = (op >> 10) & 0x3f; - dest = (op >> 4) & 0x3f; - - /* - * Stack frame creation happens in a number of ways.. in the - * general case when the stack frame is less than 511 bytes, - * it's generally created by an addi or addi.l: - * - * addi/addi.l r15, -FRAME_SIZE, r15 - * - * in the event that the frame size is bigger than this, it's - * typically created using a movi/sub pair as follows: - * - * movi FRAME_SIZE, rX - * sub r15, rX, r15 - */ - - switch (major) { - case (0x00 >> 2): - switch (minor) { - case 0x8: /* add.l */ - case 0x9: /* add */ - /* Look for r15, r63, r14 */ - if (src == 15 && disp == 63 && dest == 14) - found_prologue_end = 1; - - break; - case 0xa: /* sub.l */ - case 0xb: /* sub */ - if (src != 15 || dest != 15) - continue; - - fp_displacement -= regcache[disp]; - fp_prev = fp - fp_displacement; - break; - } - break; - case (0xa8 >> 2): /* st.l */ - if (src != 15) - continue; - - switch (dest) { - case 14: - if (offset_r14 || fp_displacement == 0) - continue; - - offset_r14 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - offset_r14 *= sizeof(unsigned long); - offset_r14 += fp_displacement; - break; - case 18: - if (offset_r18 || fp_displacement == 0) - continue; - - offset_r18 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - offset_r18 *= sizeof(unsigned long); - offset_r18 += fp_displacement; - break; - } - - break; - case (0xcc >> 2): /* movi */ - if (dest >= 63) { - printk(KERN_NOTICE "%s: Invalid dest reg %d " - "specified in movi handler. Failed " - "opcode was 0x%lx: ", __FUNCTION__, - dest, op); - - continue; - } - - /* Sign extend */ - regcache[dest] = - ((((s64)(u64)op >> 10) & 0xffff) << 54) >> 54; - break; - case (0xd0 >> 2): /* addi */ - case (0xd4 >> 2): /* addi.l */ - /* Look for r15, -FRAME_SIZE, r15 */ - if (src != 15 || dest != 15) - continue; - - /* Sign extended frame size.. */ - fp_displacement += - (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); - fp_prev = fp - fp_displacement; - break; - } - - if (found_prologue_end && offset_r14 && (offset_r18 || *pprev_pc) && fp_prev) - break; - } - - if (offset_r14 == 0 || fp_prev == 0) { - if (!offset_r14) - pr_debug("Unable to find r14 offset\n"); - if (!fp_prev) - pr_debug("Unable to find previous fp\n"); - - return -EINVAL; - } - - /* For innermost leaf function, there might not be a offset_r18 */ - if (!*pprev_pc && (offset_r18 == 0)) - return -EINVAL; - - *pprev_fp = *(unsigned long *)(fp_prev + offset_r14); - - if (offset_r18) - *pprev_pc = *(unsigned long *)(fp_prev + offset_r18); - - *pprev_pc &= ~1; - - return 0; -} - -/* Don't put this on the stack since we'll want to call sh64_unwind - * when we're close to underflowing the stack anyway. */ -static struct pt_regs here_regs; - -extern const char syscall_ret; -extern const char ret_from_syscall; -extern const char ret_from_exception; -extern const char ret_from_irq; - -static void sh64_unwind_inner(struct pt_regs *regs); - -static void unwind_nested (unsigned long pc, unsigned long fp) -{ - if ((fp >= __MEMORY_START) && - ((fp & 7) == 0)) { - sh64_unwind_inner((struct pt_regs *) fp); - } -} - -static void sh64_unwind_inner(struct pt_regs *regs) -{ - unsigned long pc, fp; - int ofs = 0; - int first_pass; - - pc = regs->pc & ~1; - fp = regs->regs[14]; - - first_pass = 1; - for (;;) { - int cond; - unsigned long next_fp, next_pc; - - if (pc == ((unsigned long) &syscall_ret & ~1)) { - printk("SYSCALL\n"); - unwind_nested(pc,fp); - return; - } - - if (pc == ((unsigned long) &ret_from_syscall & ~1)) { - printk("SYSCALL (PREEMPTED)\n"); - unwind_nested(pc,fp); - return; - } - - /* In this case, the PC is discovered by lookup_prev_stack_frame but - it has 4 taken off it to look like the 'caller' */ - if (pc == ((unsigned long) &ret_from_exception & ~1)) { - printk("EXCEPTION\n"); - unwind_nested(pc,fp); - return; - } - - if (pc == ((unsigned long) &ret_from_irq & ~1)) { - printk("IRQ\n"); - unwind_nested(pc,fp); - return; - } - - cond = ((pc >= __MEMORY_START) && (fp >= __MEMORY_START) && - ((pc & 3) == 0) && ((fp & 7) == 0)); - - pc -= ofs; - - printk("[<%08lx>] ", pc); - print_symbol("%s\n", pc); - - if (first_pass) { - /* If the innermost frame is a leaf function, it's - * possible that r18 is never saved out to the stack. - */ - next_pc = regs->regs[18]; - } else { - next_pc = 0; - } - - if (lookup_prev_stack_frame(fp, pc, &next_fp, &next_pc, regs) == 0) { - ofs = sizeof(unsigned long); - pc = next_pc & ~1; - fp = next_fp; - } else { - printk("Unable to lookup previous stack frame\n"); - break; - } - first_pass = 0; - } - - printk("\n"); - -} - -void sh64_unwind(struct pt_regs *regs) -{ - if (!regs) { - /* - * Fetch current regs if we have no other saved state to back - * trace from. - */ - regs = &here_regs; - - __asm__ __volatile__ ("ori r14, 0, %0" : "=r" (regs->regs[14])); - __asm__ __volatile__ ("ori r15, 0, %0" : "=r" (regs->regs[15])); - __asm__ __volatile__ ("ori r18, 0, %0" : "=r" (regs->regs[18])); - - __asm__ __volatile__ ("gettr tr0, %0" : "=r" (regs->tregs[0])); - __asm__ __volatile__ ("gettr tr1, %0" : "=r" (regs->tregs[1])); - __asm__ __volatile__ ("gettr tr2, %0" : "=r" (regs->tregs[2])); - __asm__ __volatile__ ("gettr tr3, %0" : "=r" (regs->tregs[3])); - __asm__ __volatile__ ("gettr tr4, %0" : "=r" (regs->tregs[4])); - __asm__ __volatile__ ("gettr tr5, %0" : "=r" (regs->tregs[5])); - __asm__ __volatile__ ("gettr tr6, %0" : "=r" (regs->tregs[6])); - __asm__ __volatile__ ("gettr tr7, %0" : "=r" (regs->tregs[7])); - - __asm__ __volatile__ ( - "pta 0f, tr0\n\t" - "blink tr0, %0\n\t" - "0: nop" - : "=r" (regs->pc) - ); - } - - printk("\nCall Trace:\n"); - sh64_unwind_inner(regs); -} - diff -puN arch/sh64/kernel/vmlinux.lds.S~git-sh /dev/null --- a/arch/sh64/kernel/vmlinux.lds.S +++ /dev/null @@ -1,140 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh5/vmlinux.lds.S - * - * ld script to make ST50 Linux kernel - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * benedict.gaster@superh.com: 2nd May 2002 - * Add definition of empty_zero_page to be the first page of kernel image. - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - * - * lethal@linux-sh.org: 9th May 2003 - * Kill off GLOBAL_NAME() usage and other CDC-isms. - * - * lethal@linux-sh.org: 19th May 2003 - * Remove support for ancient toolchains. - */ - -#include -#include -#include -#include - -#define LOAD_OFFSET CONFIG_CACHED_MEMORY_OFFSET -#include - -OUTPUT_ARCH(sh:sh5) - -#define C_PHYS(x) AT (ADDR(x) - LOAD_OFFSET) - -ENTRY(__start) -SECTIONS -{ - . = CONFIG_CACHED_MEMORY_OFFSET + CONFIG_MEMORY_START + PAGE_SIZE; - _text = .; /* Text and read-only data */ - text = .; /* Text and read-only data */ - - .empty_zero_page : C_PHYS(.empty_zero_page) { - *(.empty_zero_page) - } = 0 - - .text : C_PHYS(.text) { - *(.text.head) - TEXT_TEXT - *(.text64) - *(.text..SHmedia32) - SCHED_TEXT - LOCK_TEXT - *(.fixup) - *(.gnu.warning) -#ifdef CONFIG_LITTLE_ENDIAN - } = 0x6ff0fff0 -#else - } = 0xf0fff06f -#endif - - /* We likely want __ex_table to be Cache Line aligned */ - . = ALIGN(L1_CACHE_BYTES); /* Exception table */ - __start___ex_table = .; - __ex_table : C_PHYS(__ex_table) { *(__ex_table) } - __stop___ex_table = .; - - _etext = .; /* End of text section */ - - NOTES - - RODATA - - .data : C_PHYS(.data) { /* Data */ - DATA_DATA - CONSTRUCTORS - } - - . = ALIGN(PAGE_SIZE); - .data.page_aligned : C_PHYS(.data.page_aligned) { *(.data.page_aligned) } - - PERCPU(PAGE_SIZE) - - . = ALIGN(L1_CACHE_BYTES); - .data.cacheline_aligned : C_PHYS(.data.cacheline_aligned) { *(.data.cacheline_aligned) } - - _edata = .; /* End of data section */ - - . = ALIGN(THREAD_SIZE); /* init_task: structure size aligned */ - .data.init_task : C_PHYS(.data.init_task) { *(.data.init_task) } - - . = ALIGN(PAGE_SIZE); /* Init code and data */ - __init_begin = .; - _sinittext = .; - .init.text : C_PHYS(.init.text) { *(.init.text) } - _einittext = .; - .init.data : C_PHYS(.init.data) { *(.init.data) } - . = ALIGN(L1_CACHE_BYTES); /* Better if Cache Line aligned */ - __setup_start = .; - .init.setup : C_PHYS(.init.setup) { *(.init.setup) } - __setup_end = .; - __initcall_start = .; - .initcall.init : C_PHYS(.initcall.init) { - INITCALLS - } - __initcall_end = .; - __con_initcall_start = .; - .con_initcall.init : C_PHYS(.con_initcall.init) { *(.con_initcall.init) } - __con_initcall_end = .; - SECURITY_INIT - -#ifdef CONFIG_BLK_DEV_INITRD - __initramfs_start = .; - .init.ramfs : C_PHYS(.init.ramfs) { *(.init.ramfs) } - __initramfs_end = .; -#endif - - . = ALIGN(PAGE_SIZE); - __init_end = .; - - /* Align to the biggest single data representation, head and tail */ - . = ALIGN(8); - __bss_start = .; /* BSS */ - .bss : C_PHYS(.bss) { - *(.bss) - } - . = ALIGN(8); - _end = . ; - - /* Sections to be discarded */ - /DISCARD/ : { - *(.exit.text) - *(.exit.data) - *(.exitcall.exit) - } - - STABS_DEBUG - DWARF_DEBUG -} diff -puN arch/sh64/lib/.gitignore~git-sh /dev/null --- a/arch/sh64/lib/.gitignore +++ /dev/null @@ -1 +0,0 @@ -syscalltab.h diff -puN arch/sh64/lib/Makefile~git-sh /dev/null --- a/arch/sh64/lib/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2000, 2001 Paolo Alberelli -# Coprygith (C) 2003 Paul Mundt -# -# Makefile for the SH-5 specific library files.. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -# Panic should really be compiled as PIC -lib-y := udelay.o c-checksum.o dbg.o io.o panic.o memcpy.o copy_user_memcpy.o \ - page_copy.o page_clear.o iomap.o - diff -puN arch/sh64/lib/c-checksum.c~git-sh /dev/null --- a/arch/sh64/lib/c-checksum.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * arch/sh64/lib/c-checksum.c - * - * This file contains network checksum routines that are better done - * in an architecture-specific manner due to speed.. - */ - -#undef DEBUG - -#include -#include -#include -#include -#include -#include - -static inline unsigned short from64to16(unsigned long long x) -{ - /* add up 32-bit words for 33 bits */ - x = (x & 0xffffffff) + (x >> 32); - /* add up 16-bit and 17-bit words for 17+c bits */ - x = (x & 0xffff) + (x >> 16); - /* add up 16-bit and 2-bit for 16+c bit */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static inline unsigned short foldto16(unsigned long x) -{ - /* add up 16-bit for 17 bits */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -static inline unsigned short myfoldto16(unsigned long long x) -{ - /* Fold down to 32-bits so we don't loose in the typedef-less - network stack. */ - /* 64 to 33 */ - x = (x & 0xffffffff) + (x >> 32); - /* 33 to 32 */ - x = (x & 0xffffffff) + (x >> 32); - - /* add up 16-bit for 17 bits */ - x = (x & 0xffff) + (x >> 16); - /* add up carry.. */ - x = (x & 0xffff) + (x >> 16); - return x; -} - -#define odd(x) ((x)&1) -#define U16(x) ntohs(x) - -static unsigned long do_csum(const unsigned char *buff, int len) -{ - int odd, count; - unsigned long result = 0; - - pr_debug("do_csum buff %p, len %d (0x%x)\n", buff, len, len); -#ifdef DEBUG - for (i = 0; i < len; i++) { - if ((i % 26) == 0) - printk("\n"); - printk("%02X ", buff[i]); - } -#endif - - if (len <= 0) - goto out; - - odd = 1 & (unsigned long) buff; - if (odd) { - result = *buff << 8; - len--; - buff++; - } - count = len >> 1; /* nr of 16-bit words.. */ - if (count) { - if (2 & (unsigned long) buff) { - result += *(unsigned short *) buff; - count--; - len -= 2; - buff += 2; - } - count >>= 1; /* nr of 32-bit words.. */ - if (count) { - unsigned long carry = 0; - do { - unsigned long w = *(unsigned long *) buff; - buff += 4; - count--; - result += carry; - result += w; - carry = (w > result); - } while (count); - result += carry; - result = (result & 0xffff) + (result >> 16); - } - if (len & 2) { - result += *(unsigned short *) buff; - buff += 2; - } - } - if (len & 1) - result += *buff; - result = foldto16(result); - if (odd) - result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); - - pr_debug("\nCHECKSUM is 0x%lx\n", result); - - out: - return result; -} - -/* computes the checksum of a memory block at buff, length len, - and adds in "sum" (32-bit) */ -__wsum csum_partial(const void *buff, int len, __wsum sum) -{ - unsigned long long result = do_csum(buff, len); - - /* add in old sum, and carry.. */ - result += (__force u32)sum; - /* 32+c bits -> 32 bits */ - result = (result & 0xffffffff) + (result >> 32); - - pr_debug("csum_partial, buff %p len %d sum 0x%x result=0x%016Lx\n", - buff, len, sum, result); - - return (__force __wsum)result; -} - -/* Copy while checksumming, otherwise like csum_partial. */ -__wsum -csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum) -{ - sum = csum_partial(src, len, sum); - memcpy(dst, src, len); - - return sum; -} - -/* Copy from userspace and compute checksum. If we catch an exception - then zero the rest of the buffer. */ -__wsum -csum_partial_copy_from_user(const void __user *src, void *dst, int len, - __wsum sum, int *err_ptr) -{ - int missing; - - pr_debug - ("csum_partial_copy_from_user src %p, dest %p, len %d, sum %08x, err_ptr %p\n", - src, dst, len, sum, err_ptr); - missing = copy_from_user(dst, src, len); - pr_debug(" access_ok %d\n", __access_ok((unsigned long) src, len)); - pr_debug(" missing %d\n", missing); - if (missing) { - memset(dst + len - missing, 0, missing); - *err_ptr = -EFAULT; - } - - return csum_partial(dst, len, sum); -} - -/* Copy to userspace and compute checksum. */ -__wsum -csum_partial_copy_to_user(const unsigned char *src, unsigned char *dst, int len, - __wsum sum, int *err_ptr) -{ - sum = csum_partial(src, len, sum); - - if (copy_to_user(dst, src, len)) - *err_ptr = -EFAULT; - - return sum; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - */ -__sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - pr_debug("ip_fast_csum %p,%d\n", iph, ihl); - - return (__force __sum16)~do_csum(iph, ihl * 4); -} - -__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, __wsum sum) -{ - unsigned long long result; - - pr_debug("ntohs(0x%x)=0x%x\n", 0xdead, ntohs(0xdead)); - pr_debug("htons(0x%x)=0x%x\n", 0xdead, htons(0xdead)); - - result = (__force u64) saddr + (__force u64) daddr + - (__force u64) sum + ((len + proto) << 8); - - /* Fold down to 32-bits so we don't loose in the typedef-less - network stack. */ - /* 64 to 33 */ - result = (result & 0xffffffff) + (result >> 32); - /* 33 to 32 */ - result = (result & 0xffffffff) + (result >> 32); - - pr_debug("%s saddr %x daddr %x len %x proto %x sum %x result %08Lx\n", - __FUNCTION__, saddr, daddr, len, proto, sum, result); - - return (__wsum)result; -} -EXPORT_SYMBOL(csum_tcpudp_nofold); diff -puN arch/sh64/lib/copy_user_memcpy.S~git-sh /dev/null --- a/arch/sh64/lib/copy_user_memcpy.S +++ /dev/null @@ -1,217 +0,0 @@ -! -! Fast SH memcpy -! -! by Toshiyasu Morita (tm@netcom.com) -! hacked by J"orn Rernnecke (joern.rennecke@superh.com) ("o for o-umlaut) -! SH5 code Copyright 2002 SuperH Ltd. -! -! Entry: ARG0: destination pointer -! ARG1: source pointer -! ARG2: byte count -! -! Exit: RESULT: destination pointer -! any other registers in the range r0-r7: trashed -! -! Notes: Usually one wants to do small reads and write a longword, but -! unfortunately it is difficult in some cases to concatanate bytes -! into a longword on the SH, so this does a longword read and small -! writes. -! -! This implementation makes two assumptions about how it is called: -! -! 1.: If the byte count is nonzero, the address of the last byte to be -! copied is unsigned greater than the address of the first byte to -! be copied. This could be easily swapped for a signed comparison, -! but the algorithm used needs some comparison. -! -! 2.: When there are two or three bytes in the last word of an 11-or-more -! bytes memory chunk to b copied, the rest of the word can be read -! without side effects. -! This could be easily changed by increasing the minumum size of -! a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2, -! however, this would cost a few extra cyles on average. -! For SHmedia, the assumption is that any quadword can be read in its -! enirety if at least one byte is included in the copy. - -/* Imported into Linux kernel by Richard Curnow. This is used to implement the - __copy_user function in the general case, so it has to be a distinct - function from intra-kernel memcpy to allow for exception fix-ups in the - event that the user pointer is bad somewhere in the copy (e.g. due to - running off the end of the vma). - - Note, this algorithm will be slightly wasteful in the case where the source - and destination pointers are equally aligned, because the stlo/sthi pairs - could then be merged back into single stores. If there are a lot of cache - misses, this is probably offset by the stall lengths on the preloads. - -*/ - -/* NOTE : Prefetches removed and allocos guarded by synco to avoid TAKum03020 - * erratum. The first two prefetches are nop-ed out to avoid upsetting the - * instruction counts used in the jump address calculation. - * */ - - .section .text..SHmedia32,"ax" - .little - .balign 32 - .global copy_user_memcpy - .global copy_user_memcpy_end -copy_user_memcpy: - -#define LDUAQ(P,O,D0,D1) ldlo.q P,O,D0; ldhi.q P,O+7,D1 -#define STUAQ(P,O,D0,D1) stlo.q P,O,D0; sthi.q P,O+7,D1 -#define LDUAL(P,O,D0,D1) ldlo.l P,O,D0; ldhi.l P,O+3,D1 -#define STUAL(P,O,D0,D1) stlo.l P,O,D0; sthi.l P,O+3,D1 - - nop ! ld.b r3,0,r63 ! TAKum03020 - pta/l Large,tr0 - movi 25,r0 - bgeu/u r4,r0,tr0 - nsb r4,r0 - shlli r0,5,r0 - movi (L1-L0+63*32 + 1) & 0xffff,r1 - sub r1, r0, r0 -L0: ptrel r0,tr0 - add r2,r4,r5 - ptabs r18,tr1 - add r3,r4,r6 - blink tr0,r63 - -/* Rearranged to make cut2 safe */ - .balign 8 -L4_7: /* 4..7 byte memcpy cntd. */ - stlo.l r2, 0, r0 - or r6, r7, r6 - sthi.l r5, -1, r6 - stlo.l r5, -4, r6 - blink tr1,r63 - - .balign 8 -L1: /* 0 byte memcpy */ - nop - blink tr1,r63 - nop - nop - nop - nop - -L2_3: /* 2 or 3 byte memcpy cntd. */ - st.b r5,-1,r6 - blink tr1,r63 - - /* 1 byte memcpy */ - ld.b r3,0,r0 - st.b r2,0,r0 - blink tr1,r63 - -L8_15: /* 8..15 byte memcpy cntd. */ - stlo.q r2, 0, r0 - or r6, r7, r6 - sthi.q r5, -1, r6 - stlo.q r5, -8, r6 - blink tr1,r63 - - /* 2 or 3 byte memcpy */ - ld.b r3,0,r0 - nop ! ld.b r2,0,r63 ! TAKum03020 - ld.b r3,1,r1 - st.b r2,0,r0 - pta/l L2_3,tr0 - ld.b r6,-1,r6 - st.b r2,1,r1 - blink tr0, r63 - - /* 4 .. 7 byte memcpy */ - LDUAL (r3, 0, r0, r1) - pta L4_7, tr0 - ldlo.l r6, -4, r7 - or r0, r1, r0 - sthi.l r2, 3, r0 - ldhi.l r6, -1, r6 - blink tr0, r63 - - /* 8 .. 15 byte memcpy */ - LDUAQ (r3, 0, r0, r1) - pta L8_15, tr0 - ldlo.q r6, -8, r7 - or r0, r1, r0 - sthi.q r2, 7, r0 - ldhi.q r6, -1, r6 - blink tr0, r63 - - /* 16 .. 24 byte memcpy */ - LDUAQ (r3, 0, r0, r1) - LDUAQ (r3, 8, r8, r9) - or r0, r1, r0 - sthi.q r2, 7, r0 - or r8, r9, r8 - sthi.q r2, 15, r8 - ldlo.q r6, -8, r7 - ldhi.q r6, -1, r6 - stlo.q r2, 8, r8 - stlo.q r2, 0, r0 - or r6, r7, r6 - sthi.q r5, -1, r6 - stlo.q r5, -8, r6 - blink tr1,r63 - -Large: - ! ld.b r2, 0, r63 ! TAKum03020 - pta/l Loop_ua, tr1 - ori r3, -8, r7 - sub r2, r7, r22 - sub r3, r2, r6 - add r2, r4, r5 - ldlo.q r3, 0, r0 - addi r5, -16, r5 - movi 64+8, r27 ! could subtract r7 from that. - stlo.q r2, 0, r0 - sthi.q r2, 7, r0 - ldx.q r22, r6, r0 - bgtu/l r27, r4, tr1 - - addi r5, -48, r27 - pta/l Loop_line, tr0 - addi r6, 64, r36 - addi r6, -24, r19 - addi r6, -16, r20 - addi r6, -8, r21 - -Loop_line: - ! ldx.q r22, r36, r63 ! TAKum03020 - alloco r22, 32 - synco - addi r22, 32, r22 - ldx.q r22, r19, r23 - sthi.q r22, -25, r0 - ldx.q r22, r20, r24 - ldx.q r22, r21, r25 - stlo.q r22, -32, r0 - ldx.q r22, r6, r0 - sthi.q r22, -17, r23 - sthi.q r22, -9, r24 - sthi.q r22, -1, r25 - stlo.q r22, -24, r23 - stlo.q r22, -16, r24 - stlo.q r22, -8, r25 - bgeu r27, r22, tr0 - -Loop_ua: - addi r22, 8, r22 - sthi.q r22, -1, r0 - stlo.q r22, -8, r0 - ldx.q r22, r6, r0 - bgtu/l r5, r22, tr1 - - add r3, r4, r7 - ldlo.q r7, -8, r1 - sthi.q r22, 7, r0 - ldhi.q r7, -1, r7 - ptabs r18,tr1 - stlo.q r22, 0, r0 - or r1, r7, r1 - sthi.q r5, 15, r1 - stlo.q r5, 8, r1 - blink tr1, r63 -copy_user_memcpy_end: - nop diff -puN arch/sh64/lib/dbg.c~git-sh /dev/null --- a/arch/sh64/lib/dbg.c +++ /dev/null @@ -1,430 +0,0 @@ -/*-------------------------------------------------------------------------- --- --- Identity : Linux50 Debug Funcions --- --- File : arch/sh64/lib/dbg.C --- --- Copyright 2000, 2001 STMicroelectronics Limited. --- Copyright 2004 Richard Curnow (evt_debug etc) --- ---------------------------------------------------------------------------*/ -#include -#include -#include -#include -#include -#include - -typedef u64 regType_t; - -static regType_t getConfigReg(u64 id) -{ - register u64 reg __asm__("r2"); - asm volatile ("getcfg %1, 0, %0":"=r" (reg):"r"(id)); - return (reg); -} - -/* ======================================================================= */ - -static char *szTab[] = { "4k", "64k", "1M", "512M" }; -static char *protTab[] = { "----", - "---R", - "--X-", - "--XR", - "-W--", - "-W-R", - "-WX-", - "-WXR", - "U---", - "U--R", - "U-X-", - "U-XR", - "UW--", - "UW-R", - "UWX-", - "UWXR" -}; -#define ITLB_BASE 0x00000000 -#define DTLB_BASE 0x00800000 -#define MAX_TLBs 64 -/* PTE High */ -#define GET_VALID(pte) ((pte) & 0x1) -#define GET_SHARED(pte) ((pte) & 0x2) -#define GET_ASID(pte) ((pte >> 2) & 0x0ff) -#define GET_EPN(pte) ((pte) & 0xfffff000) - -/* PTE Low */ -#define GET_CBEHAVIOR(pte) ((pte) & 0x3) -#define GET_PAGE_SIZE(pte) szTab[((pte >> 3) & 0x3)] -#define GET_PROTECTION(pte) protTab[((pte >> 6) & 0xf)] -#define GET_PPN(pte) ((pte) & 0xfffff000) - -#define PAGE_1K_MASK 0x00000000 -#define PAGE_4K_MASK 0x00000010 -#define PAGE_64K_MASK 0x00000080 -#define MMU_PAGESIZE_MASK (PAGE_64K_MASK | PAGE_4K_MASK) -#define PAGE_1MB_MASK MMU_PAGESIZE_MASK -#define PAGE_1K (1024) -#define PAGE_4K (1024 * 4) -#define PAGE_64K (1024 * 64) -#define PAGE_1MB (1024 * 1024) - -#define HOW_TO_READ_TLB_CONTENT \ - "[ ID] PPN EPN ASID Share CB P.Size PROT.\n" - -void print_single_tlb(unsigned long tlb, int single_print) -{ - regType_t pteH; - regType_t pteL; - unsigned int valid, shared, asid, epn, cb, ppn; - char *pSize; - char *pProt; - - /* - ** in case of single print is true, this implies: - ** 1) print the TLB in any case also if NOT VALID - ** 2) print out the header - */ - - pteH = getConfigReg(tlb); - valid = GET_VALID(pteH); - if (single_print) - printk(HOW_TO_READ_TLB_CONTENT); - else if (!valid) - return; - - pteL = getConfigReg(tlb + 1); - - shared = GET_SHARED(pteH); - asid = GET_ASID(pteH); - epn = GET_EPN(pteH); - cb = GET_CBEHAVIOR(pteL); - pSize = GET_PAGE_SIZE(pteL); - pProt = GET_PROTECTION(pteL); - ppn = GET_PPN(pteL); - printk("[%c%2ld] 0x%08x 0x%08x %03d %02x %02x %4s %s\n", - ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP), - ppn, epn, asid, shared, cb, pSize, pProt); -} - -void print_dtlb(void) -{ - int count; - unsigned long tlb; - - printk(" ================= SH-5 D-TLBs Status ===================\n"); - printk(HOW_TO_READ_TLB_CONTENT); - tlb = DTLB_BASE; - for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) - print_single_tlb(tlb, 0); - printk - (" =============================================================\n"); -} - -void print_itlb(void) -{ - int count; - unsigned long tlb; - - printk(" ================= SH-5 I-TLBs Status ===================\n"); - printk(HOW_TO_READ_TLB_CONTENT); - tlb = ITLB_BASE; - for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP) - print_single_tlb(tlb, 0); - printk - (" =============================================================\n"); -} - -/* ======================================================================= */ - -#ifdef CONFIG_POOR_MANS_STRACE - -#include "syscalltab.h" - -struct ring_node { - int evt; - int ret_addr; - int event; - int tra; - int pid; - unsigned long sp; - unsigned long pc; -}; - -static struct ring_node event_ring[16]; -static int event_ptr = 0; - -struct stored_syscall_data { - int pid; - int syscall_number; -}; - -#define N_STORED_SYSCALLS 16 - -static struct stored_syscall_data stored_syscalls[N_STORED_SYSCALLS]; -static int syscall_next=0; -static int syscall_next_print=0; - -void evt_debug(int evt, int ret_addr, int event, int tra, struct pt_regs *regs) -{ - int syscallno = tra & 0xff; - unsigned long sp; - unsigned long stack_bottom; - int pid; - struct ring_node *rr; - - pid = current->pid; - stack_bottom = (unsigned long) task_stack_page(current); - asm volatile("ori r15, 0, %0" : "=r" (sp)); - rr = event_ring + event_ptr; - rr->evt = evt; - rr->ret_addr = ret_addr; - rr->event = event; - rr->tra = tra; - rr->pid = pid; - rr->sp = sp; - rr->pc = regs->pc; - - if (sp < stack_bottom + 3092) { - printk("evt_debug : stack underflow report\n"); - int i, j; - for (j=0, i = event_ptr; j<16; j++) { - rr = event_ring + i; - printk("evt=%08x event=%08x tra=%08x pid=%5d sp=%08lx pc=%08lx\n", - rr->evt, rr->event, rr->tra, rr->pid, rr->sp, rr->pc); - i--; - i &= 15; - } - panic("STACK UNDERFLOW\n"); - } - - event_ptr = (event_ptr + 1) & 15; - - if ((event == 2) && (evt == 0x160)) { - if (syscallno < NUM_SYSCALL_INFO_ENTRIES) { - /* Store the syscall information to print later. We - * can't print this now - currently we're running with - * SR.BL=1, so we can't take a tlbmiss (which could occur - * in the console drivers under printk). - * - * Just overwrite old entries on ring overflow - this - * is only for last-hope debugging. */ - stored_syscalls[syscall_next].pid = current->pid; - stored_syscalls[syscall_next].syscall_number = syscallno; - syscall_next++; - syscall_next &= (N_STORED_SYSCALLS - 1); - } - } -} - -static void drain_syscalls(void) { - while (syscall_next_print != syscall_next) { - printk("Task %d: %s()\n", - stored_syscalls[syscall_next_print].pid, - syscall_info_table[stored_syscalls[syscall_next_print].syscall_number].name); - syscall_next_print++; - syscall_next_print &= (N_STORED_SYSCALLS - 1); - } -} - -void evt_debug2(unsigned int ret) -{ - drain_syscalls(); - printk("Task %d: syscall returns %08x\n", current->pid, ret); -} - -void evt_debug_ret_from_irq(struct pt_regs *regs) -{ - int pid; - struct ring_node *rr; - - pid = current->pid; - rr = event_ring + event_ptr; - rr->evt = 0xffff; - rr->ret_addr = 0; - rr->event = 0; - rr->tra = 0; - rr->pid = pid; - rr->pc = regs->pc; - event_ptr = (event_ptr + 1) & 15; -} - -void evt_debug_ret_from_exc(struct pt_regs *regs) -{ - int pid; - struct ring_node *rr; - - pid = current->pid; - rr = event_ring + event_ptr; - rr->evt = 0xfffe; - rr->ret_addr = 0; - rr->event = 0; - rr->tra = 0; - rr->pid = pid; - rr->pc = regs->pc; - event_ptr = (event_ptr + 1) & 15; -} - -#endif /* CONFIG_POOR_MANS_STRACE */ - -/* ======================================================================= */ - -void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs) -{ - - unsigned long long ah, al, bh, bl, ch, cl; - - printk("\n"); - printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n", - ((from) ? from : "???"), current->pid, trapnr, signr); - - asm volatile ("getcon " __EXPEVT ", %0":"=r"(ah)); - asm volatile ("getcon " __EXPEVT ", %0":"=r"(al)); - ah = (ah) >> 32; - al = (al) & 0xffffffff; - asm volatile ("getcon " __KCR1 ", %0":"=r"(bh)); - asm volatile ("getcon " __KCR1 ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __INTEVT ", %0":"=r"(ch)); - asm volatile ("getcon " __INTEVT ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - asm volatile ("getcon " __PEXPEVT ", %0":"=r"(ah)); - asm volatile ("getcon " __PEXPEVT ", %0":"=r"(al)); - ah = (ah) >> 32; - al = (al) & 0xffffffff; - asm volatile ("getcon " __PSPC ", %0":"=r"(bh)); - asm volatile ("getcon " __PSPC ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __PSSR ", %0":"=r"(ch)); - asm volatile ("getcon " __PSSR ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->pc) >> 32; - al = (regs->pc) & 0xffffffff; - bh = (regs->regs[18]) >> 32; - bl = (regs->regs[18]) & 0xffffffff; - ch = (regs->regs[15]) >> 32; - cl = (regs->regs[15]) & 0xffffffff; - printk("PC : %08Lx%08Lx LINK: %08Lx%08Lx SP : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->sr) >> 32; - al = (regs->sr) & 0xffffffff; - asm volatile ("getcon " __TEA ", %0":"=r"(bh)); - asm volatile ("getcon " __TEA ", %0":"=r"(bl)); - bh = (bh) >> 32; - bl = (bl) & 0xffffffff; - asm volatile ("getcon " __KCR0 ", %0":"=r"(ch)); - asm volatile ("getcon " __KCR0 ", %0":"=r"(cl)); - ch = (ch) >> 32; - cl = (cl) & 0xffffffff; - printk("SR : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[0]) >> 32; - al = (regs->regs[0]) & 0xffffffff; - bh = (regs->regs[1]) >> 32; - bl = (regs->regs[1]) & 0xffffffff; - ch = (regs->regs[2]) >> 32; - cl = (regs->regs[2]) & 0xffffffff; - printk("R0 : %08Lx%08Lx R1 : %08Lx%08Lx R2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[3]) >> 32; - al = (regs->regs[3]) & 0xffffffff; - bh = (regs->regs[4]) >> 32; - bl = (regs->regs[4]) & 0xffffffff; - ch = (regs->regs[5]) >> 32; - cl = (regs->regs[5]) & 0xffffffff; - printk("R3 : %08Lx%08Lx R4 : %08Lx%08Lx R5 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[6]) >> 32; - al = (regs->regs[6]) & 0xffffffff; - bh = (regs->regs[7]) >> 32; - bl = (regs->regs[7]) & 0xffffffff; - ch = (regs->regs[8]) >> 32; - cl = (regs->regs[8]) & 0xffffffff; - printk("R6 : %08Lx%08Lx R7 : %08Lx%08Lx R8 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - - ah = (regs->regs[9]) >> 32; - al = (regs->regs[9]) & 0xffffffff; - bh = (regs->regs[10]) >> 32; - bl = (regs->regs[10]) & 0xffffffff; - ch = (regs->regs[11]) >> 32; - cl = (regs->regs[11]) & 0xffffffff; - printk("R9 : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - printk("....\n"); - - ah = (regs->tregs[0]) >> 32; - al = (regs->tregs[0]) & 0xffffffff; - bh = (regs->tregs[1]) >> 32; - bl = (regs->tregs[1]) & 0xffffffff; - ch = (regs->tregs[2]) >> 32; - cl = (regs->tregs[2]) & 0xffffffff; - printk("T0 : %08Lx%08Lx T1 : %08Lx%08Lx T2 : %08Lx%08Lx\n", - ah, al, bh, bl, ch, cl); - printk("....\n"); - - print_dtlb(); - print_itlb(); -} - -/* ======================================================================= */ - -/* -** Depending on scan the MMU, Data or Instruction side -** looking for a valid mapping matching Eaddr & asid. -** Return -1 if not found or the TLB id entry otherwise. -** Note: it works only for 4k pages! -*/ -static unsigned long -lookup_mmu_side(unsigned long base, unsigned long Eaddr, unsigned long asid) -{ - regType_t pteH; - unsigned long epn; - int count; - - epn = Eaddr & 0xfffff000; - - for (count = 0; count < MAX_TLBs; count++, base += TLB_STEP) { - pteH = getConfigReg(base); - if (GET_VALID(pteH)) - if ((unsigned long) GET_EPN(pteH) == epn) - if ((unsigned long) GET_ASID(pteH) == asid) - break; - } - return ((unsigned long) ((count < MAX_TLBs) ? base : -1)); -} - -unsigned long lookup_dtlb(unsigned long Eaddr) -{ - unsigned long asid = get_asid(); - return (lookup_mmu_side((u64) DTLB_BASE, Eaddr, asid)); -} - -unsigned long lookup_itlb(unsigned long Eaddr) -{ - unsigned long asid = get_asid(); - return (lookup_mmu_side((u64) ITLB_BASE, Eaddr, asid)); -} - -void print_page(struct page *page) -{ - printk(" page[%p] -> index 0x%lx, count 0x%x, flags 0x%lx\n", - page, page->index, page_count(page), page->flags); - printk(" address_space = %p, pages =%ld\n", page->mapping, - page->mapping->nrpages); - -} diff -puN arch/sh64/lib/io.c~git-sh /dev/null --- a/arch/sh64/lib/io.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (C) 2000 David J. Mckay (david.mckay@st.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * This file contains the I/O routines for use on the overdrive board - * - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Now for the string version of these functions */ -void outsb(unsigned long port, const void *addr, unsigned long count) -{ - int i; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p++) { - outb(*p, port); - } -} -EXPORT_SYMBOL(outsb); - -void insb(unsigned long port, void *addr, unsigned long count) -{ - int i; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p++) { - *p = inb(port); - } -} -EXPORT_SYMBOL(insb); - -/* For the 16 and 32 bit string functions, we have to worry about alignment. - * The SH does not do unaligned accesses, so we have to read as bytes and - * then write as a word or dword. - * This can be optimised a lot more, especially in the case where the data - * is aligned - */ - -void outsw(unsigned long port, const void *addr, unsigned long count) -{ - int i; - unsigned short tmp; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p += 2) { - tmp = (*p) | ((*(p + 1)) << 8); - outw(tmp, port); - } -} -EXPORT_SYMBOL(outsw); - -void insw(unsigned long port, void *addr, unsigned long count) -{ - int i; - unsigned short tmp; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p += 2) { - tmp = inw(port); - p[0] = tmp & 0xff; - p[1] = (tmp >> 8) & 0xff; - } -} -EXPORT_SYMBOL(insw); - -void outsl(unsigned long port, const void *addr, unsigned long count) -{ - int i; - unsigned tmp; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p += 4) { - tmp = (*p) | ((*(p + 1)) << 8) | ((*(p + 2)) << 16) | - ((*(p + 3)) << 24); - outl(tmp, port); - } -} -EXPORT_SYMBOL(outsl); - -void insl(unsigned long port, void *addr, unsigned long count) -{ - int i; - unsigned tmp; - unsigned char *p = (unsigned char *) addr; - - for (i = 0; i < count; i++, p += 4) { - tmp = inl(port); - p[0] = tmp & 0xff; - p[1] = (tmp >> 8) & 0xff; - p[2] = (tmp >> 16) & 0xff; - p[3] = (tmp >> 24) & 0xff; - - } -} -EXPORT_SYMBOL(insl); - -void memcpy_toio(void __iomem *to, const void *from, long count) -{ - unsigned char *p = (unsigned char *) from; - - while (count) { - count--; - writeb(*p++, to++); - } -} -EXPORT_SYMBOL(memcpy_toio); - -void memcpy_fromio(void *to, void __iomem *from, long count) -{ - int i; - unsigned char *p = (unsigned char *) to; - - for (i = 0; i < count; i++) { - p[i] = readb(from); - from++; - } -} -EXPORT_SYMBOL(memcpy_fromio); diff -puN arch/sh64/lib/iomap.c~git-sh /dev/null --- a/arch/sh64/lib/iomap.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * arch/sh64/lib/iomap.c - * - * Generic sh64 iomap interface - * - * Copyright (C) 2004 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include - -void __iomem *__attribute__ ((weak)) -ioport_map(unsigned long port, unsigned int len) -{ - return (void __iomem *)port; -} -EXPORT_SYMBOL(ioport_map); - -void ioport_unmap(void __iomem *addr) -{ - /* Nothing .. */ -} -EXPORT_SYMBOL(ioport_unmap); - -#ifdef CONFIG_PCI -void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max) -{ - 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) - return NULL; - if (max && len > max) - len = max; - if (flags & IORESOURCE_IO) - return ioport_map(start + pciio_virt, len); - if (flags & IORESOURCE_MEM) - return (void __iomem *)start; - - /* What? */ - return NULL; -} -EXPORT_SYMBOL(pci_iomap); - -void pci_iounmap(struct pci_dev *dev, void __iomem *addr) -{ - /* Nothing .. */ -} -EXPORT_SYMBOL(pci_iounmap); -#endif diff -puN arch/sh64/lib/memcpy.c~git-sh /dev/null --- a/arch/sh64/lib/memcpy.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2002 Mark Debbage (Mark.Debbage@superh.com) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - */ - -#include -#include - -// This is a simplistic optimization of memcpy to increase the -// granularity of access beyond one byte using aligned -// loads and stores. This is not an optimal implementation -// for SH-5 (especially with regard to prefetching and the cache), -// and a better version should be provided later ... - -void *memcpy(void *dest, const void *src, size_t count) -{ - char *d = (char *) dest, *s = (char *) src; - - if (count >= 32) { - int i = 8 - (((unsigned long) d) & 0x7); - - if (i != 8) - while (i-- && count--) { - *d++ = *s++; - } - - if (((((unsigned long) d) & 0x7) == 0) && - ((((unsigned long) s) & 0x7) == 0)) { - while (count >= 32) { - unsigned long long t1, t2, t3, t4; - t1 = *(unsigned long long *) (s); - t2 = *(unsigned long long *) (s + 8); - t3 = *(unsigned long long *) (s + 16); - t4 = *(unsigned long long *) (s + 24); - *(unsigned long long *) (d) = t1; - *(unsigned long long *) (d + 8) = t2; - *(unsigned long long *) (d + 16) = t3; - *(unsigned long long *) (d + 24) = t4; - d += 32; - s += 32; - count -= 32; - } - while (count >= 8) { - *(unsigned long long *) d = - *(unsigned long long *) s; - d += 8; - s += 8; - count -= 8; - } - } - - if (((((unsigned long) d) & 0x3) == 0) && - ((((unsigned long) s) & 0x3) == 0)) { - while (count >= 4) { - *(unsigned long *) d = *(unsigned long *) s; - d += 4; - s += 4; - count -= 4; - } - } - - if (((((unsigned long) d) & 0x1) == 0) && - ((((unsigned long) s) & 0x1) == 0)) { - while (count >= 2) { - *(unsigned short *) d = *(unsigned short *) s; - d += 2; - s += 2; - count -= 2; - } - } - } - - while (count--) { - *d++ = *s++; - } - - return d; -} diff -puN arch/sh64/lib/page_clear.S~git-sh /dev/null --- a/arch/sh64/lib/page_clear.S +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright 2003 Richard Curnow, SuperH (UK) Ltd. - - This file is subject to the terms and conditions of the GNU General Public - License. See the file "COPYING" in the main directory of this archive - for more details. - - Tight version of memset for the case of just clearing a page. It turns out - that having the alloco's spaced out slightly due to the increment/branch - pair causes them to contend less for access to the cache. Similarly, - keeping the stores apart from the allocos causes less contention. => Do two - separate loops. Do multiple stores per loop to amortise the - increment/branch cost a little. - - Parameters: - r2 : source effective address (start of page) - - Always clears 4096 bytes. - - Note : alloco guarded by synco to avoid TAKum03020 erratum - -*/ - - .section .text..SHmedia32,"ax" - .little - - .balign 8 - .global sh64_page_clear -sh64_page_clear: - pta/l 1f, tr1 - pta/l 2f, tr2 - ptabs/l r18, tr0 - - movi 4096, r7 - add r2, r7, r7 - add r2, r63, r6 -1: - alloco r6, 0 - synco ! TAKum03020 - addi r6, 32, r6 - bgt/l r7, r6, tr1 - - add r2, r63, r6 -2: - st.q r6, 0, r63 - st.q r6, 8, r63 - st.q r6, 16, r63 - st.q r6, 24, r63 - addi r6, 32, r6 - bgt/l r7, r6, tr2 - - blink tr0, r63 - - diff -puN arch/sh64/lib/page_copy.S~git-sh /dev/null --- a/arch/sh64/lib/page_copy.S +++ /dev/null @@ -1,91 +0,0 @@ -/* - Copyright 2003 Richard Curnow, SuperH (UK) Ltd. - - This file is subject to the terms and conditions of the GNU General Public - License. See the file "COPYING" in the main directory of this archive - for more details. - - Tight version of mempy for the case of just copying a page. - Prefetch strategy empirically optimised against RTL simulations - of SH5-101 cut2 eval chip with Cayman board DDR memory. - - Parameters: - r2 : source effective address (start of page) - r3 : destination effective address (start of page) - - Always copies 4096 bytes. - - Points to review. - * Currently the prefetch is 4 lines ahead and the alloco is 2 lines ahead. - It seems like the prefetch needs to be at at least 4 lines ahead to get - the data into the cache in time, and the allocos contend with outstanding - prefetches for the same cache set, so it's better to have the numbers - different. - */ - - .section .text..SHmedia32,"ax" - .little - - .balign 8 - .global sh64_page_copy -sh64_page_copy: - - /* Copy 4096 bytes worth of data from r2 to r3. - Do prefetches 4 lines ahead. - Do alloco 2 lines ahead */ - - pta 1f, tr1 - pta 2f, tr2 - pta 3f, tr3 - ptabs r18, tr0 - -#if 0 - /* TAKum03020 */ - ld.q r2, 0x00, r63 - ld.q r2, 0x20, r63 - ld.q r2, 0x40, r63 - ld.q r2, 0x60, r63 -#endif - alloco r3, 0x00 - synco ! TAKum03020 - alloco r3, 0x20 - synco ! TAKum03020 - - movi 3968, r6 - add r3, r6, r6 - addi r6, 64, r7 - addi r7, 64, r8 - sub r2, r3, r60 - addi r60, 8, r61 - addi r61, 8, r62 - addi r62, 8, r23 - addi r60, 0x80, r22 - -/* Minimal code size. The extra branches inside the loop don't cost much - because they overlap with the time spent waiting for prefetches to - complete. */ -1: -#if 0 - /* TAKum03020 */ - bge/u r3, r6, tr2 ! skip prefetch for last 4 lines - ldx.q r3, r22, r63 ! prefetch 4 lines hence -#endif -2: - bge/u r3, r7, tr3 ! skip alloco for last 2 lines - alloco r3, 0x40 ! alloc destination line 2 lines ahead - synco ! TAKum03020 -3: - ldx.q r3, r60, r36 - ldx.q r3, r61, r37 - ldx.q r3, r62, r38 - ldx.q r3, r23, r39 - st.q r3, 0, r36 - st.q r3, 8, r37 - st.q r3, 16, r38 - st.q r3, 24, r39 - addi r3, 32, r3 - bgt/l r8, r3, tr1 - - blink tr0, r63 ! return - - diff -puN arch/sh64/lib/panic.c~git-sh /dev/null --- a/arch/sh64/lib/panic.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2003 Richard Curnow, SuperH UK Limited - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include - -/* THIS IS A PHYSICAL ADDRESS */ -#define HDSP2534_ADDR (0x04002100) - -#ifdef CONFIG_SH_CAYMAN - -static void poor_mans_delay(void) -{ - int i; - for (i = 0; i < 2500000; i++) { - } /* poor man's delay */ -} - -static void show_value(unsigned long x) -{ - int i; - unsigned nibble; - for (i = 0; i < 8; i++) { - nibble = ((x >> (i * 4)) & 0xf); - - ctrl_outb(nibble + ((nibble > 9) ? 55 : 48), - HDSP2534_ADDR + 0xe0 + ((7 - i) << 2)); - } -} - -#endif - -void -panic_handler(unsigned long panicPC, unsigned long panicSSR, - unsigned long panicEXPEVT) -{ -#ifdef CONFIG_SH_CAYMAN - while (1) { - /* This piece of code displays the PC on the LED display */ - show_value(panicPC); - poor_mans_delay(); - show_value(panicSSR); - poor_mans_delay(); - show_value(panicEXPEVT); - poor_mans_delay(); - } -#endif - - /* Never return from the panic handler */ - for (;;) ; - -} diff -puN arch/sh64/lib/udelay.c~git-sh /dev/null --- a/arch/sh64/lib/udelay.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * arch/sh64/lib/udelay.c - * - * Delay routines, using a pre-computed "loops_per_jiffy" value. - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include - -extern unsigned long loops_per_jiffy; - -/* - * Use only for very small delays (< 1 msec). - * - * The active part of our cycle counter is only 32-bits wide, and - * we're treating the difference between two marks as signed. On - * a 1GHz box, that's about 2 seconds. - */ - -void __delay(int loops) -{ - long long dummy; - __asm__ __volatile__("gettr tr0, %1\n\t" - "pta $+4, tr0\n\t" - "addi %0, -1, %0\n\t" - "bne %0, r63, tr0\n\t" - "ptabs %1, tr0\n\t":"=r"(loops), - "=r"(dummy) - :"0"(loops)); -} - -void __udelay(unsigned long long usecs, unsigned long lpj) -{ - usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj; - __delay((long long) usecs >> 32); -} - -void __ndelay(unsigned long long nsecs, unsigned long lpj) -{ - nsecs *= (((unsigned long long) HZ << 32) / 1000000000) * lpj; - __delay((long long) nsecs >> 32); -} - -void udelay(unsigned long usecs) -{ - __udelay(usecs, loops_per_jiffy); -} - -void ndelay(unsigned long nsecs) -{ - __ndelay(nsecs, loops_per_jiffy); -} - diff -puN arch/sh64/mach-cayman/Makefile~git-sh /dev/null --- a/arch/sh64/mach-cayman/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -# -# Makefile for the Hitachi Cayman specific parts of the kernel -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -obj-y := setup.o irq.o iomap.o -obj-$(CONFIG_HEARTBEAT) += led.o - diff -puN arch/sh64/mach-cayman/iomap.c~git-sh /dev/null --- a/arch/sh64/mach-cayman/iomap.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * arch/sh64/mach-cayman/iomap.c - * - * Cayman iomap interface - * - * Copyright (C) 2004 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include - -void __iomem *ioport_map(unsigned long port, unsigned int len) -{ - if (port < 0x400) - return (void __iomem *)((port << 2) | smsc_superio_virt); - - return (void __iomem *)port; -} - diff -puN arch/sh64/mach-cayman/irq.c~git-sh /dev/null --- a/arch/sh64/mach-cayman/irq.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/kernel/irq_cayman.c - * - * SH-5 Cayman Interrupt Support - * - * This file handles the board specific parts of the Cayman interrupt system - * - * Copyright (C) 2002 Stuart Menefy - */ - -#include -#include -#include -#include -#include -#include -#include - -unsigned long epld_virt; - -#define EPLD_BASE 0x04002000 -#define EPLD_STATUS_BASE (epld_virt + 0x10) -#define EPLD_MASK_BASE (epld_virt + 0x20) - -/* Note the SMSC SuperIO chip and SMSC LAN chip interrupts are all muxed onto - the same SH-5 interrupt */ - -static irqreturn_t cayman_interrupt_smsc(int irq, void *dev_id) -{ - printk(KERN_INFO "CAYMAN: spurious SMSC interrupt\n"); - return IRQ_NONE; -} - -static irqreturn_t cayman_interrupt_pci2(int irq, void *dev_id) -{ - printk(KERN_INFO "CAYMAN: spurious PCI interrupt, IRQ %d\n", irq); - return IRQ_NONE; -} - -static struct irqaction cayman_action_smsc = { - .name = "Cayman SMSC Mux", - .handler = cayman_interrupt_smsc, - .flags = IRQF_DISABLED, -}; - -static struct irqaction cayman_action_pci2 = { - .name = "Cayman PCI2 Mux", - .handler = cayman_interrupt_pci2, - .flags = IRQF_DISABLED, -}; - -static void enable_cayman_irq(unsigned int irq) -{ - unsigned long flags; - unsigned long mask; - unsigned int reg; - unsigned char bit; - - irq -= START_EXT_IRQS; - reg = EPLD_MASK_BASE + ((irq / 8) << 2); - bit = 1<<(irq % 8); - local_irq_save(flags); - mask = ctrl_inl(reg); - mask |= bit; - ctrl_outl(mask, reg); - local_irq_restore(flags); -} - -void disable_cayman_irq(unsigned int irq) -{ - unsigned long flags; - unsigned long mask; - unsigned int reg; - unsigned char bit; - - irq -= START_EXT_IRQS; - reg = EPLD_MASK_BASE + ((irq / 8) << 2); - bit = 1<<(irq % 8); - local_irq_save(flags); - mask = ctrl_inl(reg); - mask &= ~bit; - ctrl_outl(mask, reg); - local_irq_restore(flags); -} - -static void ack_cayman_irq(unsigned int irq) -{ - disable_cayman_irq(irq); -} - -static void end_cayman_irq(unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) - enable_cayman_irq(irq); -} - -static unsigned int startup_cayman_irq(unsigned int irq) -{ - enable_cayman_irq(irq); - return 0; /* never anything pending */ -} - -static void shutdown_cayman_irq(unsigned int irq) -{ - disable_cayman_irq(irq); -} - -struct hw_interrupt_type cayman_irq_type = { - .typename = "Cayman-IRQ", - .startup = startup_cayman_irq, - .shutdown = shutdown_cayman_irq, - .enable = enable_cayman_irq, - .disable = disable_cayman_irq, - .ack = ack_cayman_irq, - .end = end_cayman_irq, -}; - -int cayman_irq_demux(int evt) -{ - int irq = intc_evt_to_irq[evt]; - - if (irq == SMSC_IRQ) { - unsigned long status; - int i; - - status = ctrl_inl(EPLD_STATUS_BASE) & - ctrl_inl(EPLD_MASK_BASE) & 0xff; - if (status == 0) { - irq = -1; - } else { - for (i=0; i<8; i++) { - if (status & (1<= NR_INTC_IRQS + 24) && (irq < NR_INTC_IRQS + 32)) { - return sprintf(p, "(PCI2 %d)", irq - (NR_INTC_IRQS + 24)); - } - - return 0; -} -#endif - -void init_cayman_irq(void) -{ - int i; - - epld_virt = onchip_remap(EPLD_BASE, 1024, "EPLD"); - if (!epld_virt) { - printk(KERN_ERR "Cayman IRQ: Unable to remap EPLD\n"); - return; - } - - for (i=0; i - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Flash the LEDs - */ -#include - -/* -** It is supposed these functions to be used for a low level -** debugging (via Cayman LEDs), hence to be available as soon -** as possible. -** Unfortunately Cayman LEDs relies on Cayman EPLD to be mapped -** (this happen when IRQ are initialized... quite late). -** These triky dependencies should be removed. Temporary, it -** may be enough to NOP until EPLD is mapped. -*/ - -extern unsigned long epld_virt; - -#define LED_ADDR (epld_virt + 0x008) -#define HDSP2534_ADDR (epld_virt + 0x100) - -void mach_led(int position, int value) -{ - if (!epld_virt) - return; - - if (value) - ctrl_outl(0, LED_ADDR); - else - ctrl_outl(1, LED_ADDR); - -} - -void mach_alphanum(int position, unsigned char value) -{ - if (!epld_virt) - return; - - ctrl_outb(value, HDSP2534_ADDR + 0xe0 + (position << 2)); -} - -void mach_alphanum_brightness(int setting) -{ - ctrl_outb(setting & 7, HDSP2534_ADDR + 0xc0); -} diff -puN arch/sh64/mach-cayman/setup.c~git-sh /dev/null --- a/arch/sh64/mach-cayman/setup.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mach-cayman/setup.c - * - * SH5 Cayman support - * - * This file handles the architecture-dependent parts of initialization - * - * Copyright David J. Mckay. - * Needs major work! - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - * - * lethal@linux-sh.org: 15th May 2003 - * Use the generic procfs cpuinfo interface, just return a valid board name. - */ -#include -#include -#include -#include -#include - -/* - * Platform Dependent Interrupt Priorities. - */ - -/* Using defaults defined in irq.h */ -#define RES NO_PRIORITY /* Disabled */ -#define IR0 IRL0_PRIORITY /* IRLs */ -#define IR1 IRL1_PRIORITY -#define IR2 IRL2_PRIORITY -#define IR3 IRL3_PRIORITY -#define PCA INTA_PRIORITY /* PCI Ints */ -#define PCB INTB_PRIORITY -#define PCC INTC_PRIORITY -#define PCD INTD_PRIORITY -#define SER TOP_PRIORITY -#define ERR TOP_PRIORITY -#define PW0 TOP_PRIORITY -#define PW1 TOP_PRIORITY -#define PW2 TOP_PRIORITY -#define PW3 TOP_PRIORITY -#define DM0 NO_PRIORITY /* DMA Ints */ -#define DM1 NO_PRIORITY -#define DM2 NO_PRIORITY -#define DM3 NO_PRIORITY -#define DAE NO_PRIORITY -#define TU0 TIMER_PRIORITY /* TMU Ints */ -#define TU1 NO_PRIORITY -#define TU2 NO_PRIORITY -#define TI2 NO_PRIORITY -#define ATI NO_PRIORITY /* RTC Ints */ -#define PRI NO_PRIORITY -#define CUI RTC_PRIORITY -#define ERI SCIF_PRIORITY /* SCIF Ints */ -#define RXI SCIF_PRIORITY -#define BRI SCIF_PRIORITY -#define TXI SCIF_PRIORITY -#define ITI TOP_PRIORITY /* WDT Ints */ - -/* Setup for the SMSC FDC37C935 */ -#define SMSC_SUPERIO_BASE 0x04000000 -#define SMSC_CONFIG_PORT_ADDR 0x3f0 -#define SMSC_INDEX_PORT_ADDR SMSC_CONFIG_PORT_ADDR -#define SMSC_DATA_PORT_ADDR 0x3f1 - -#define SMSC_ENTER_CONFIG_KEY 0x55 -#define SMSC_EXIT_CONFIG_KEY 0xaa - -#define SMCS_LOGICAL_DEV_INDEX 0x07 -#define SMSC_DEVICE_ID_INDEX 0x20 -#define SMSC_DEVICE_REV_INDEX 0x21 -#define SMSC_ACTIVATE_INDEX 0x30 -#define SMSC_PRIMARY_BASE_INDEX 0x60 -#define SMSC_SECONDARY_BASE_INDEX 0x62 -#define SMSC_PRIMARY_INT_INDEX 0x70 -#define SMSC_SECONDARY_INT_INDEX 0x72 - -#define SMSC_IDE1_DEVICE 1 -#define SMSC_KEYBOARD_DEVICE 7 -#define SMSC_CONFIG_REGISTERS 8 - -#define SMSC_SUPERIO_READ_INDEXED(index) ({ \ - outb((index), SMSC_INDEX_PORT_ADDR); \ - inb(SMSC_DATA_PORT_ADDR); }) -#define SMSC_SUPERIO_WRITE_INDEXED(val, index) ({ \ - outb((index), SMSC_INDEX_PORT_ADDR); \ - outb((val), SMSC_DATA_PORT_ADDR); }) - -#define IDE1_PRIMARY_BASE 0x01f0 -#define IDE1_SECONDARY_BASE 0x03f6 - -unsigned long smsc_superio_virt; - -/* - * Platform dependent structures: maps and parms block. - */ -struct resource io_resources[] = { - /* To be updated with external devices */ -}; - -struct resource kram_resources[] = { - /* These must be last in the array */ - { .name = "Kernel code", .start = 0, .end = 0 }, - /* These must be last in the array */ - { .name = "Kernel data", .start = 0, .end = 0 } -}; - -struct resource xram_resources[] = { - /* To be updated with external devices */ -}; - -struct resource rom_resources[] = { - /* To be updated with external devices */ -}; - -struct sh64_platform platform_parms = { - .readonly_rootfs = 1, - .initial_root_dev = 0x0100, - .loader_type = 1, - .io_res_p = io_resources, - .io_res_count = ARRAY_SIZE(io_resources), - .kram_res_p = kram_resources, - .kram_res_count = ARRAY_SIZE(kram_resources), - .xram_res_p = xram_resources, - .xram_res_count = ARRAY_SIZE(xram_resources), - .rom_res_p = rom_resources, - .rom_res_count = ARRAY_SIZE(rom_resources), -}; - -int platform_int_priority[NR_INTC_IRQS] = { - IR0, IR1, IR2, IR3, PCA, PCB, PCC, PCD, /* IRQ 0- 7 */ - RES, RES, RES, RES, SER, ERR, PW3, PW2, /* IRQ 8-15 */ - PW1, PW0, DM0, DM1, DM2, DM3, DAE, RES, /* IRQ 16-23 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 24-31 */ - TU0, TU1, TU2, TI2, ATI, PRI, CUI, ERI, /* IRQ 32-39 */ - RXI, BRI, TXI, RES, RES, RES, RES, RES, /* IRQ 40-47 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 48-55 */ - RES, RES, RES, RES, RES, RES, RES, ITI, /* IRQ 56-63 */ -}; - -static int __init smsc_superio_setup(void) -{ - unsigned char devid, devrev; - - smsc_superio_virt = onchip_remap(SMSC_SUPERIO_BASE, 1024, "SMSC SuperIO"); - if (!smsc_superio_virt) { - panic("Unable to remap SMSC SuperIO\n"); - } - - /* Initially the chip is in run state */ - /* Put it into configuration state */ - outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); - outb(SMSC_ENTER_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); - - /* Read device ID info */ - devid = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_ID_INDEX); - devrev = SMSC_SUPERIO_READ_INDEXED(SMSC_DEVICE_REV_INDEX); - printk("SMSC SuperIO devid %02x rev %02x\n", devid, devrev); - - /* Select the keyboard device */ - SMSC_SUPERIO_WRITE_INDEXED(SMSC_KEYBOARD_DEVICE, SMCS_LOGICAL_DEV_INDEX); - - /* enable it */ - SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX); - - /* Select the interrupts */ - /* On a PC keyboard is IRQ1, mouse is IRQ12 */ - SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_PRIMARY_INT_INDEX); - SMSC_SUPERIO_WRITE_INDEXED(12, SMSC_SECONDARY_INT_INDEX); - -#ifdef CONFIG_IDE - /* - * Only IDE1 exists on the Cayman - */ - - /* Power it on */ - SMSC_SUPERIO_WRITE_INDEXED(1 << SMSC_IDE1_DEVICE, 0x22); - - SMSC_SUPERIO_WRITE_INDEXED(SMSC_IDE1_DEVICE, SMCS_LOGICAL_DEV_INDEX); - SMSC_SUPERIO_WRITE_INDEXED(1, SMSC_ACTIVATE_INDEX); - - SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE >> 8, - SMSC_PRIMARY_BASE_INDEX + 0); - SMSC_SUPERIO_WRITE_INDEXED(IDE1_PRIMARY_BASE & 0xff, - SMSC_PRIMARY_BASE_INDEX + 1); - - SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE >> 8, - SMSC_SECONDARY_BASE_INDEX + 0); - SMSC_SUPERIO_WRITE_INDEXED(IDE1_SECONDARY_BASE & 0xff, - SMSC_SECONDARY_BASE_INDEX + 1); - - SMSC_SUPERIO_WRITE_INDEXED(14, SMSC_PRIMARY_INT_INDEX); - - SMSC_SUPERIO_WRITE_INDEXED(SMSC_CONFIG_REGISTERS, - SMCS_LOGICAL_DEV_INDEX); - - SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc2); /* GP42 = nIDE1_OE */ - SMSC_SUPERIO_WRITE_INDEXED(0x01, 0xc5); /* GP45 = IDE1_IRQ */ - SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc6); /* GP46 = nIOROP */ - SMSC_SUPERIO_WRITE_INDEXED(0x00, 0xc7); /* GP47 = nIOWOP */ -#endif - - /* Exit the configuration state */ - outb(SMSC_EXIT_CONFIG_KEY, SMSC_CONFIG_PORT_ADDR); - - return 0; -} - -/* This is grotty, but, because kernel is always referenced on the link line - * before any devices, this is safe. - */ -__initcall(smsc_superio_setup); - -void __init platform_setup(void) -{ - /* Cayman platform leaves the decision to head.S, for now */ - platform_parms.fpu_flags = fpu_in_use; -} - -void __init platform_monitor(void) -{ - /* Nothing yet .. */ -} - -void __init platform_reserve(void) -{ - /* Nothing yet .. */ -} - -const char *get_system_type(void) -{ - return "Hitachi Cayman"; -} - diff -puN arch/sh64/mach-harp/Makefile~git-sh /dev/null --- a/arch/sh64/mach-harp/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y := setup.o diff -puN arch/sh64/mach-harp/setup.c~git-sh /dev/null --- a/arch/sh64/mach-harp/setup.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mach-harp/setup.c - * - * SH-5 Simulator Platform Support - * - * This file handles the architecture-dependent parts of initialization - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. * - * - * lethal@linux-sh.org: 15th May 2003 - * Use the generic procfs cpuinfo interface, just return a valid board name. - */ -#include -#include -#include -#include - -/* - * Platform Dependent Interrupt Priorities. - */ - -/* Using defaults defined in irq.h */ -#define RES NO_PRIORITY /* Disabled */ -#define IR0 IRL0_PRIORITY /* IRLs */ -#define IR1 IRL1_PRIORITY -#define IR2 IRL2_PRIORITY -#define IR3 IRL3_PRIORITY -#define PCA INTA_PRIORITY /* PCI Ints */ -#define PCB INTB_PRIORITY -#define PCC INTC_PRIORITY -#define PCD INTD_PRIORITY -#define SER TOP_PRIORITY -#define ERR TOP_PRIORITY -#define PW0 TOP_PRIORITY -#define PW1 TOP_PRIORITY -#define PW2 TOP_PRIORITY -#define PW3 TOP_PRIORITY -#define DM0 NO_PRIORITY /* DMA Ints */ -#define DM1 NO_PRIORITY -#define DM2 NO_PRIORITY -#define DM3 NO_PRIORITY -#define DAE NO_PRIORITY -#define TU0 TIMER_PRIORITY /* TMU Ints */ -#define TU1 NO_PRIORITY -#define TU2 NO_PRIORITY -#define TI2 NO_PRIORITY -#define ATI NO_PRIORITY /* RTC Ints */ -#define PRI NO_PRIORITY -#define CUI RTC_PRIORITY -#define ERI SCIF_PRIORITY /* SCIF Ints */ -#define RXI SCIF_PRIORITY -#define BRI SCIF_PRIORITY -#define TXI SCIF_PRIORITY -#define ITI TOP_PRIORITY /* WDT Ints */ - -/* - * Platform dependent structures: maps and parms block. - */ -struct resource io_resources[] = { - /* To be updated with external devices */ -}; - -struct resource kram_resources[] = { - /* These must be last in the array */ - { .name = "Kernel code", .start = 0, .end = 0 }, - /* These must be last in the array */ - { .name = "Kernel data", .start = 0, .end = 0 } -}; - -struct resource xram_resources[] = { - /* To be updated with external devices */ -}; - -struct resource rom_resources[] = { - /* To be updated with external devices */ -}; - -struct sh64_platform platform_parms = { - .readonly_rootfs = 1, - .initial_root_dev = 0x0100, - .loader_type = 1, - .io_res_p = io_resources, - .io_res_count = ARRAY_SIZE(io_resources), - .kram_res_p = kram_resources, - .kram_res_count = ARRAY_SIZE(kram_resources), - .xram_res_p = xram_resources, - .xram_res_count = ARRAY_SIZE(xram_resources), - .rom_res_p = rom_resources, - .rom_res_count = ARRAY_SIZE(rom_resources), -}; - -int platform_int_priority[NR_INTC_IRQS] = { - IR0, IR1, IR2, IR3, PCA, PCB, PCC, PCD, /* IRQ 0- 7 */ - RES, RES, RES, RES, SER, ERR, PW3, PW2, /* IRQ 8-15 */ - PW1, PW0, DM0, DM1, DM2, DM3, DAE, RES, /* IRQ 16-23 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 24-31 */ - TU0, TU1, TU2, TI2, ATI, PRI, CUI, ERI, /* IRQ 32-39 */ - RXI, BRI, TXI, RES, RES, RES, RES, RES, /* IRQ 40-47 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 48-55 */ - RES, RES, RES, RES, RES, RES, RES, ITI, /* IRQ 56-63 */ -}; - -void __init platform_setup(void) -{ - /* Harp platform leaves the decision to head.S, for now */ - platform_parms.fpu_flags = fpu_in_use; -} - -void __init platform_monitor(void) -{ - /* Nothing yet .. */ -} - -void __init platform_reserve(void) -{ - /* Nothing yet .. */ -} - -const char *get_system_type(void) -{ - return "ST50 Harp"; -} diff -puN arch/sh64/mach-sim/Makefile~git-sh /dev/null --- a/arch/sh64/mach-sim/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-y := setup.o diff -puN arch/sh64/mach-sim/setup.c~git-sh /dev/null --- a/arch/sh64/mach-sim/setup.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mach-sim/setup.c - * - * ST50 Simulator Platform Support - * - * This file handles the architecture-dependent parts of initialization - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * lethal@linux-sh.org: 15th May 2003 - * Use the generic procfs cpuinfo interface, just return a valid board name. - */ -#include -#include -#include -#include - -/* - * Platform Dependent Interrupt Priorities. - */ - -/* Using defaults defined in irq.h */ -#define RES NO_PRIORITY /* Disabled */ -#define IR0 IRL0_PRIORITY /* IRLs */ -#define IR1 IRL1_PRIORITY -#define IR2 IRL2_PRIORITY -#define IR3 IRL3_PRIORITY -#define PCA INTA_PRIORITY /* PCI Ints */ -#define PCB INTB_PRIORITY -#define PCC INTC_PRIORITY -#define PCD INTD_PRIORITY -#define SER TOP_PRIORITY -#define ERR TOP_PRIORITY -#define PW0 TOP_PRIORITY -#define PW1 TOP_PRIORITY -#define PW2 TOP_PRIORITY -#define PW3 TOP_PRIORITY -#define DM0 NO_PRIORITY /* DMA Ints */ -#define DM1 NO_PRIORITY -#define DM2 NO_PRIORITY -#define DM3 NO_PRIORITY -#define DAE NO_PRIORITY -#define TU0 TIMER_PRIORITY /* TMU Ints */ -#define TU1 NO_PRIORITY -#define TU2 NO_PRIORITY -#define TI2 NO_PRIORITY -#define ATI NO_PRIORITY /* RTC Ints */ -#define PRI NO_PRIORITY -#define CUI RTC_PRIORITY -#define ERI SCIF_PRIORITY /* SCIF Ints */ -#define RXI SCIF_PRIORITY -#define BRI SCIF_PRIORITY -#define TXI SCIF_PRIORITY -#define ITI TOP_PRIORITY /* WDT Ints */ - -/* - * Platform dependent structures: maps and parms block. - */ -struct resource io_resources[] = { - /* Nothing yet .. */ -}; - -struct resource kram_resources[] = { - /* These must be last in the array */ - { .name = "Kernel code", .start = 0, .end = 0 }, - /* These must be last in the array */ - { .name = "Kernel data", .start = 0, .end = 0 } -}; - -struct resource xram_resources[] = { - /* Nothing yet .. */ -}; - -struct resource rom_resources[] = { - /* Nothing yet .. */ -}; - -struct sh64_platform platform_parms = { - .readonly_rootfs = 1, - .initial_root_dev = 0x0100, - .loader_type = 1, - .io_res_p = io_resources, - .io_res_count = ARRAY_SIZE(io_resources), - .kram_res_p = kram_resources, - .kram_res_count = ARRAY_SIZE(kram_resources), - .xram_res_p = xram_resources, - .xram_res_count = ARRAY_SIZE(xram_resources), - .rom_res_p = rom_resources, - .rom_res_count = ARRAY_SIZE(rom_resources), -}; - -int platform_int_priority[NR_IRQS] = { - IR0, IR1, IR2, IR3, PCA, PCB, PCC, PCD, /* IRQ 0- 7 */ - RES, RES, RES, RES, SER, ERR, PW3, PW2, /* IRQ 8-15 */ - PW1, PW0, DM0, DM1, DM2, DM3, DAE, RES, /* IRQ 16-23 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 24-31 */ - TU0, TU1, TU2, TI2, ATI, PRI, CUI, ERI, /* IRQ 32-39 */ - RXI, BRI, TXI, RES, RES, RES, RES, RES, /* IRQ 40-47 */ - RES, RES, RES, RES, RES, RES, RES, RES, /* IRQ 48-55 */ - RES, RES, RES, RES, RES, RES, RES, ITI, /* IRQ 56-63 */ -}; - -void __init platform_setup(void) -{ - /* Simulator platform leaves the decision to head.S */ - platform_parms.fpu_flags = fpu_in_use; -} - -void __init platform_monitor(void) -{ - /* Nothing yet .. */ -} - -void __init platform_reserve(void) -{ - /* Nothing yet .. */ -} - -const char *get_system_type(void) -{ - return "SH-5 Simulator"; -} diff -puN arch/sh64/mm/Makefile~git-sh /dev/null --- a/arch/sh64/mm/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# Copyright (C) 2000, 2001 Paolo Alberelli -# Copyright (C) 2003, 2004 Paul Mundt -# -# Makefile for the sh64-specific parts of the Linux memory manager. -# -# Note! Dependencies are done automagically by 'make dep', which also -# removes any old dependencies. DON'T put your own dependencies here -# unless it's something special (ie not a .c file). -# - -obj-y := cache.o consistent.o extable.o fault.o init.o ioremap.o \ - tlbmiss.o tlb.o - -obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o - -# Special flags for tlbmiss.o. This puts restrictions on the number of -# caller-save registers that the compiler can target when building this file. -# This is required because the code is called from a context in entry.S where -# very few registers have been saved in the exception handler (for speed -# reasons). -# The caller save registers that have been saved and which can be used are -# r2,r3,r4,r5 : argument passing -# r15, r18 : SP and LINK -# tr0-4 : allow all caller-save TR's. The compiler seems to be able to make -# use of them, so it's probably beneficial to performance to save them -# and have them available for it. -# -# The resources not listed below are callee save, i.e. the compiler is free to -# use any of them and will spill them to the stack itself. - -CFLAGS_tlbmiss.o += -ffixed-r7 \ - -ffixed-r8 -ffixed-r9 -ffixed-r10 -ffixed-r11 -ffixed-r12 \ - -ffixed-r13 -ffixed-r14 -ffixed-r16 -ffixed-r17 -ffixed-r19 \ - -ffixed-r20 -ffixed-r21 -ffixed-r22 -ffixed-r23 \ - -ffixed-r24 -ffixed-r25 -ffixed-r26 -ffixed-r27 \ - -ffixed-r36 -ffixed-r37 -ffixed-r38 -ffixed-r39 -ffixed-r40 \ - -ffixed-r41 -ffixed-r42 -ffixed-r43 \ - -ffixed-r60 -ffixed-r61 -ffixed-r62 \ - -fomit-frame-pointer diff -puN arch/sh64/mm/cache.c~git-sh /dev/null --- a/arch/sh64/mm/cache.c +++ /dev/null @@ -1,1032 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/cache.c - * - * Original version Copyright (C) 2000, 2001 Paolo Alberelli - * Second version Copyright (C) benedict.gaster@superh.com 2002 - * Third version Copyright Richard.Curnow@superh.com 2003 - * Hacks to third version Copyright (C) 2003 Paul Mundt - */ - -/****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include /* for flush_itlb_range */ - -#include - -/* This function is in entry.S */ -extern unsigned long switch_and_save_asid(unsigned long new_asid); - -/* Wired TLB entry for the D-cache */ -static unsigned long long dtlb_cache_slot; - -/** - * sh64_cache_init() - * - * This is pretty much just a straightforward clone of the SH - * detect_cpu_and_cache_system(). - * - * This function is responsible for setting up all of the cache - * info dynamically as well as taking care of CPU probing and - * setting up the relevant subtype data. - * - * FIXME: For the time being, we only really support the SH5-101 - * out of the box, and don't support dynamic probing for things - * like the SH5-103 or even cut2 of the SH5-101. Implement this - * later! - */ -int __init sh64_cache_init(void) -{ - /* - * First, setup some sane values for the I-cache. - */ - cpu_data->icache.ways = 4; - cpu_data->icache.sets = 256; - cpu_data->icache.linesz = L1_CACHE_BYTES; - - /* - * FIXME: This can probably be cleaned up a bit as well.. for example, - * do we really need the way shift _and_ the way_step_shift ?? Judging - * by the existing code, I would guess no.. is there any valid reason - * why we need to be tracking this around? - */ - cpu_data->icache.way_shift = 13; - cpu_data->icache.entry_shift = 5; - cpu_data->icache.set_shift = 4; - cpu_data->icache.way_step_shift = 16; - cpu_data->icache.asid_shift = 2; - - /* - * way offset = cache size / associativity, so just don't factor in - * associativity in the first place.. - */ - cpu_data->icache.way_ofs = cpu_data->icache.sets * - cpu_data->icache.linesz; - - cpu_data->icache.asid_mask = 0x3fc; - cpu_data->icache.idx_mask = 0x1fe0; - cpu_data->icache.epn_mask = 0xffffe000; - cpu_data->icache.flags = 0; - - /* - * Next, setup some sane values for the D-cache. - * - * On the SH5, these are pretty consistent with the I-cache settings, - * so we just copy over the existing definitions.. these can be fixed - * up later, especially if we add runtime CPU probing. - * - * Though in the meantime it saves us from having to duplicate all of - * the above definitions.. - */ - cpu_data->dcache = cpu_data->icache; - - /* - * Setup any cache-related flags here - */ -#if defined(CONFIG_DCACHE_WRITE_THROUGH) - set_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags)); -#elif defined(CONFIG_DCACHE_WRITE_BACK) - set_bit(SH_CACHE_MODE_WB, &(cpu_data->dcache.flags)); -#endif - - /* - * We also need to reserve a slot for the D-cache in the DTLB, so we - * do this now .. - */ - dtlb_cache_slot = sh64_get_wired_dtlb_entry(); - - return 0; -} - -#ifdef CONFIG_DCACHE_DISABLED -#define sh64_dcache_purge_all() do { } while (0) -#define sh64_dcache_purge_coloured_phy_page(paddr, eaddr) do { } while (0) -#define sh64_dcache_purge_user_range(mm, start, end) do { } while (0) -#define sh64_dcache_purge_phy_page(paddr) do { } while (0) -#define sh64_dcache_purge_virt_page(mm, eaddr) do { } while (0) -#define sh64_dcache_purge_kernel_range(start, end) do { } while (0) -#define sh64_dcache_wback_current_user_range(start, end) do { } while (0) -#endif - -/*##########################################################################*/ - -/* From here onwards, a rewrite of the implementation, - by Richard.Curnow@superh.com. - - The major changes in this compared to the old version are; - 1. use more selective purging through OCBP instead of using ALLOCO to purge - by natural replacement. This avoids purging out unrelated cache lines - that happen to be in the same set. - 2. exploit the APIs copy_user_page and clear_user_page better - 3. be more selective about I-cache purging, in particular use invalidate_all - more sparingly. - - */ - -/*########################################################################## - SUPPORT FUNCTIONS - ##########################################################################*/ - -/****************************************************************************/ -/* The following group of functions deal with mapping and unmapping a temporary - page into the DTLB slot that have been set aside for our exclusive use. */ -/* In order to accomplish this, we use the generic interface for adding and - removing a wired slot entry as defined in arch/sh64/mm/tlb.c */ -/****************************************************************************/ - -static unsigned long slot_own_flags; - -static inline void sh64_setup_dtlb_cache_slot(unsigned long eaddr, unsigned long asid, unsigned long paddr) -{ - local_irq_save(slot_own_flags); - sh64_setup_tlb_slot(dtlb_cache_slot, eaddr, asid, paddr); -} - -static inline void sh64_teardown_dtlb_cache_slot(void) -{ - sh64_teardown_tlb_slot(dtlb_cache_slot); - local_irq_restore(slot_own_flags); -} - -/****************************************************************************/ - -#ifndef CONFIG_ICACHE_DISABLED - -static void __inline__ sh64_icache_inv_all(void) -{ - unsigned long long addr, flag, data; - unsigned int flags; - - addr=ICCR0; - flag=ICCR0_ICI; - data=0; - - /* Make this a critical section for safety (probably not strictly necessary.) */ - local_irq_save(flags); - - /* Without %1 it gets unexplicably wrong */ - asm volatile("getcfg %3, 0, %0\n\t" - "or %0, %2, %0\n\t" - "putcfg %3, 0, %0\n\t" - "synci" - : "=&r" (data) - : "0" (data), "r" (flag), "r" (addr)); - - local_irq_restore(flags); -} - -static void sh64_icache_inv_kernel_range(unsigned long start, unsigned long end) -{ - /* Invalidate range of addresses [start,end] from the I-cache, where - * the addresses lie in the kernel superpage. */ - - unsigned long long ullend, addr, aligned_start; -#if (NEFF == 32) - aligned_start = (unsigned long long)(signed long long)(signed long) start; -#else -#error "NEFF != 32" -#endif - aligned_start &= L1_CACHE_ALIGN_MASK; - addr = aligned_start; -#if (NEFF == 32) - ullend = (unsigned long long) (signed long long) (signed long) end; -#else -#error "NEFF != 32" -#endif - while (addr <= ullend) { - asm __volatile__ ("icbi %0, 0" : : "r" (addr)); - addr += L1_CACHE_BYTES; - } -} - -static void sh64_icache_inv_user_page(struct vm_area_struct *vma, unsigned long eaddr) -{ - /* If we get called, we know that vma->vm_flags contains VM_EXEC. - Also, eaddr is page-aligned. */ - - unsigned long long addr, end_addr; - unsigned long flags = 0; - unsigned long running_asid, vma_asid; - addr = eaddr; - end_addr = addr + PAGE_SIZE; - - /* Check whether we can use the current ASID for the I-cache - invalidation. For example, if we're called via - access_process_vm->flush_cache_page->here, (e.g. when reading from - /proc), 'running_asid' will be that of the reader, not of the - victim. - - Also, note the risk that we might get pre-empted between the ASID - compare and blocking IRQs, and before we regain control, the - pid->ASID mapping changes. However, the whole cache will get - invalidated when the mapping is renewed, so the worst that can - happen is that the loop below ends up invalidating somebody else's - cache entries. - */ - - running_asid = get_asid(); - vma_asid = (vma->vm_mm->context & MMU_CONTEXT_ASID_MASK); - if (running_asid != vma_asid) { - local_irq_save(flags); - switch_and_save_asid(vma_asid); - } - while (addr < end_addr) { - /* Worth unrolling a little */ - asm __volatile__("icbi %0, 0" : : "r" (addr)); - asm __volatile__("icbi %0, 32" : : "r" (addr)); - asm __volatile__("icbi %0, 64" : : "r" (addr)); - asm __volatile__("icbi %0, 96" : : "r" (addr)); - addr += 128; - } - if (running_asid != vma_asid) { - switch_and_save_asid(running_asid); - local_irq_restore(flags); - } -} - -/****************************************************************************/ - -static void sh64_icache_inv_user_page_range(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - /* Used for invalidating big chunks of I-cache, i.e. assume the range - is whole pages. If 'start' or 'end' is not page aligned, the code - is conservative and invalidates to the ends of the enclosing pages. - This is functionally OK, just a performance loss. */ - - /* See the comments below in sh64_dcache_purge_user_range() regarding - the choice of algorithm. However, for the I-cache option (2) isn't - available because there are no physical tags so aliases can't be - resolved. The icbi instruction has to be used through the user - mapping. Because icbi is cheaper than ocbp on a cache hit, it - would be cheaper to use the selective code for a large range than is - possible with the D-cache. Just assume 64 for now as a working - figure. - */ - - int n_pages; - - if (!mm) return; - - n_pages = ((end - start) >> PAGE_SHIFT); - if (n_pages >= 64) { - sh64_icache_inv_all(); - } else { - unsigned long aligned_start; - unsigned long eaddr; - unsigned long after_last_page_start; - unsigned long mm_asid, current_asid; - unsigned long long flags = 0ULL; - - mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; - current_asid = get_asid(); - - if (mm_asid != current_asid) { - /* Switch ASID and run the invalidate loop under cli */ - local_irq_save(flags); - switch_and_save_asid(mm_asid); - } - - aligned_start = start & PAGE_MASK; - after_last_page_start = PAGE_SIZE + ((end - 1) & PAGE_MASK); - - while (aligned_start < after_last_page_start) { - struct vm_area_struct *vma; - unsigned long vma_end; - vma = find_vma(mm, aligned_start); - if (!vma || (aligned_start <= vma->vm_end)) { - /* Avoid getting stuck in an error condition */ - aligned_start += PAGE_SIZE; - continue; - } - vma_end = vma->vm_end; - if (vma->vm_flags & VM_EXEC) { - /* Executable */ - eaddr = aligned_start; - while (eaddr < vma_end) { - sh64_icache_inv_user_page(vma, eaddr); - eaddr += PAGE_SIZE; - } - } - aligned_start = vma->vm_end; /* Skip to start of next region */ - } - if (mm_asid != current_asid) { - switch_and_save_asid(current_asid); - local_irq_restore(flags); - } - } -} - -static void sh64_icache_inv_user_small_range(struct mm_struct *mm, - unsigned long start, int len) -{ - - /* Invalidate a small range of user context I-cache, not necessarily - page (or even cache-line) aligned. */ - - unsigned long long eaddr = start; - unsigned long long eaddr_end = start + len; - unsigned long current_asid, mm_asid; - unsigned long long flags; - unsigned long long epage_start; - - /* Since this is used inside ptrace, the ASID in the mm context - typically won't match current_asid. We'll have to switch ASID to do - this. For safety, and given that the range will be small, do all - this under cli. - - Note, there is a hazard that the ASID in mm->context is no longer - actually associated with mm, i.e. if the mm->context has started a - new cycle since mm was last active. However, this is just a - performance issue: all that happens is that we invalidate lines - belonging to another mm, so the owning process has to refill them - when that mm goes live again. mm itself can't have any cache - entries because there will have been a flush_cache_all when the new - mm->context cycle started. */ - - /* Align to start of cache line. Otherwise, suppose len==8 and start - was at 32N+28 : the last 4 bytes wouldn't get invalidated. */ - eaddr = start & L1_CACHE_ALIGN_MASK; - eaddr_end = start + len; - - local_irq_save(flags); - mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; - current_asid = switch_and_save_asid(mm_asid); - - epage_start = eaddr & PAGE_MASK; - - while (eaddr < eaddr_end) - { - asm __volatile__("icbi %0, 0" : : "r" (eaddr)); - eaddr += L1_CACHE_BYTES; - } - switch_and_save_asid(current_asid); - local_irq_restore(flags); -} - -static void sh64_icache_inv_current_user_range(unsigned long start, unsigned long end) -{ - /* The icbi instruction never raises ITLBMISS. i.e. if there's not a - cache hit on the virtual tag the instruction ends there, without a - TLB lookup. */ - - unsigned long long aligned_start; - unsigned long long ull_end; - unsigned long long addr; - - ull_end = end; - - /* Just invalidate over the range using the natural addresses. TLB - miss handling will be OK (TBC). Since it's for the current process, - either we're already in the right ASID context, or the ASIDs have - been recycled since we were last active in which case we might just - invalidate another processes I-cache entries : no worries, just a - performance drop for him. */ - aligned_start = start & L1_CACHE_ALIGN_MASK; - addr = aligned_start; - while (addr < ull_end) { - asm __volatile__ ("icbi %0, 0" : : "r" (addr)); - asm __volatile__ ("nop"); - asm __volatile__ ("nop"); - addr += L1_CACHE_BYTES; - } -} - -#endif /* !CONFIG_ICACHE_DISABLED */ - -/****************************************************************************/ - -#ifndef CONFIG_DCACHE_DISABLED - -/* Buffer used as the target of alloco instructions to purge data from cache - sets by natural eviction. -- RPC */ -#define DUMMY_ALLOCO_AREA_SIZE L1_CACHE_SIZE_BYTES + (1024 * 4) -static unsigned char dummy_alloco_area[DUMMY_ALLOCO_AREA_SIZE] __cacheline_aligned = { 0, }; - -/****************************************************************************/ - -static void __inline__ sh64_dcache_purge_sets(int sets_to_purge_base, int n_sets) -{ - /* Purge all ways in a particular block of sets, specified by the base - set number and number of sets. Can handle wrap-around, if that's - needed. */ - - int dummy_buffer_base_set; - unsigned long long eaddr, eaddr0, eaddr1; - int j; - int set_offset; - - dummy_buffer_base_set = ((int)&dummy_alloco_area & cpu_data->dcache.idx_mask) >> cpu_data->dcache.entry_shift; - set_offset = sets_to_purge_base - dummy_buffer_base_set; - - for (j=0; jdcache.sets - 1); - eaddr0 = (unsigned long long)dummy_alloco_area + (set_offset << cpu_data->dcache.entry_shift); - - /* Do one alloco which hits the required set per cache way. For - write-back mode, this will purge the #ways resident lines. There's - little point unrolling this loop because the allocos stall more if - they're too close together. */ - eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; - for (eaddr=eaddr0; eaddrdcache.way_ofs) { - asm __volatile__ ("alloco %0, 0" : : "r" (eaddr)); - asm __volatile__ ("synco"); /* TAKum03020 */ - } - - eaddr1 = eaddr0 + cpu_data->dcache.way_ofs * cpu_data->dcache.ways; - for (eaddr=eaddr0; eaddrdcache.way_ofs) { - /* Load from each address. Required because alloco is a NOP if - the cache is write-through. Write-through is a config option. */ - if (test_bit(SH_CACHE_MODE_WT, &(cpu_data->dcache.flags))) - *(volatile unsigned char *)(int)eaddr; - } - } - - /* Don't use OCBI to invalidate the lines. That costs cycles directly. - If the dummy block is just left resident, it will naturally get - evicted as required. */ - - return; -} - -/****************************************************************************/ - -static void sh64_dcache_purge_all(void) -{ - /* Purge the entire contents of the dcache. The most efficient way to - achieve this is to use alloco instructions on a region of unused - memory equal in size to the cache, thereby causing the current - contents to be discarded by natural eviction. The alternative, - namely reading every tag, setting up a mapping for the corresponding - page and doing an OCBP for the line, would be much more expensive. - */ - - sh64_dcache_purge_sets(0, cpu_data->dcache.sets); - - return; - -} - -/****************************************************************************/ - -static void sh64_dcache_purge_kernel_range(unsigned long start, unsigned long end) -{ - /* Purge the range of addresses [start,end] from the D-cache. The - addresses lie in the superpage mapping. There's no harm if we - overpurge at either end - just a small performance loss. */ - unsigned long long ullend, addr, aligned_start; -#if (NEFF == 32) - aligned_start = (unsigned long long)(signed long long)(signed long) start; -#else -#error "NEFF != 32" -#endif - aligned_start &= L1_CACHE_ALIGN_MASK; - addr = aligned_start; -#if (NEFF == 32) - ullend = (unsigned long long) (signed long long) (signed long) end; -#else -#error "NEFF != 32" -#endif - while (addr <= ullend) { - asm __volatile__ ("ocbp %0, 0" : : "r" (addr)); - addr += L1_CACHE_BYTES; - } - return; -} - -/* Assumes this address (+ (2**n_synbits) pages up from it) aren't used for - anything else in the kernel */ -#define MAGIC_PAGE0_START 0xffffffffec000000ULL - -static void sh64_dcache_purge_coloured_phy_page(unsigned long paddr, unsigned long eaddr) -{ - /* Purge the physical page 'paddr' from the cache. It's known that any - cache lines requiring attention have the same page colour as the the - address 'eaddr'. - - This relies on the fact that the D-cache matches on physical tags - when no virtual tag matches. So we create an alias for the original - page and purge through that. (Alternatively, we could have done - this by switching ASID to match the original mapping and purged - through that, but that involves ASID switching cost + probably a - TLBMISS + refill anyway.) - */ - - unsigned long long magic_page_start; - unsigned long long magic_eaddr, magic_eaddr_end; - - magic_page_start = MAGIC_PAGE0_START + (eaddr & CACHE_OC_SYN_MASK); - - /* As long as the kernel is not pre-emptible, this doesn't need to be - under cli/sti. */ - - sh64_setup_dtlb_cache_slot(magic_page_start, get_asid(), paddr); - - magic_eaddr = magic_page_start; - magic_eaddr_end = magic_eaddr + PAGE_SIZE; - while (magic_eaddr < magic_eaddr_end) { - /* Little point in unrolling this loop - the OCBPs are blocking - and won't go any quicker (i.e. the loop overhead is parallel - to part of the OCBP execution.) */ - asm __volatile__ ("ocbp %0, 0" : : "r" (magic_eaddr)); - magic_eaddr += L1_CACHE_BYTES; - } - - sh64_teardown_dtlb_cache_slot(); -} - -/****************************************************************************/ - -static void sh64_dcache_purge_phy_page(unsigned long paddr) -{ - /* Pure a page given its physical start address, by creating a - temporary 1 page mapping and purging across that. Even if we know - the virtual address (& vma or mm) of the page, the method here is - more elegant because it avoids issues of coping with page faults on - the purge instructions (i.e. no special-case code required in the - critical path in the TLB miss handling). */ - - unsigned long long eaddr_start, eaddr, eaddr_end; - int i; - - /* As long as the kernel is not pre-emptible, this doesn't need to be - under cli/sti. */ - - eaddr_start = MAGIC_PAGE0_START; - for (i=0; i < (1 << CACHE_OC_N_SYNBITS); i++) { - sh64_setup_dtlb_cache_slot(eaddr_start, get_asid(), paddr); - - eaddr = eaddr_start; - eaddr_end = eaddr + PAGE_SIZE; - while (eaddr < eaddr_end) { - asm __volatile__ ("ocbp %0, 0" : : "r" (eaddr)); - eaddr += L1_CACHE_BYTES; - } - - sh64_teardown_dtlb_cache_slot(); - eaddr_start += PAGE_SIZE; - } -} - -static void sh64_dcache_purge_user_pages(struct mm_struct *mm, - unsigned long addr, unsigned long end) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - spinlock_t *ptl; - unsigned long paddr; - - if (!mm) - return; /* No way to find physical address of page */ - - pgd = pgd_offset(mm, addr); - if (pgd_bad(*pgd)) - return; - - pmd = pmd_offset(pgd, addr); - if (pmd_none(*pmd) || pmd_bad(*pmd)) - return; - - pte = pte_offset_map_lock(mm, pmd, addr, &ptl); - do { - entry = *pte; - if (pte_none(entry) || !pte_present(entry)) - continue; - paddr = pte_val(entry) & PAGE_MASK; - sh64_dcache_purge_coloured_phy_page(paddr, addr); - } while (pte++, addr += PAGE_SIZE, addr != end); - pte_unmap_unlock(pte - 1, ptl); -} -/****************************************************************************/ - -static void sh64_dcache_purge_user_range(struct mm_struct *mm, - unsigned long start, unsigned long end) -{ - /* There are at least 5 choices for the implementation of this, with - pros (+), cons(-), comments(*): - - 1. ocbp each line in the range through the original user's ASID - + no lines spuriously evicted - - tlbmiss handling (must either handle faults on demand => extra - special-case code in tlbmiss critical path), or map the page in - advance (=> flush_tlb_range in advance to avoid multiple hits) - - ASID switching - - expensive for large ranges - - 2. temporarily map each page in the range to a special effective - address and ocbp through the temporary mapping; relies on the - fact that SH-5 OCB* always do TLB lookup and match on ptags (they - never look at the etags) - + no spurious evictions - - expensive for large ranges - * surely cheaper than (1) - - 3. walk all the lines in the cache, check the tags, if a match - occurs create a page mapping to ocbp the line through - + no spurious evictions - - tag inspection overhead - - (especially for small ranges) - - potential cost of setting up/tearing down page mapping for - every line that matches the range - * cost partly independent of range size - - 4. walk all the lines in the cache, check the tags, if a match - occurs use 4 * alloco to purge the line (+3 other probably - innocent victims) by natural eviction - + no tlb mapping overheads - - spurious evictions - - tag inspection overhead - - 5. implement like flush_cache_all - + no tag inspection overhead - - spurious evictions - - bad for small ranges - - (1) can be ruled out as more expensive than (2). (2) appears best - for small ranges. The choice between (3), (4) and (5) for large - ranges and the range size for the large/small boundary need - benchmarking to determine. - - For now use approach (2) for small ranges and (5) for large ones. - - */ - - int n_pages; - - n_pages = ((end - start) >> PAGE_SHIFT); - if (n_pages >= 64 || ((start ^ (end - 1)) & PMD_MASK)) { -#if 1 - sh64_dcache_purge_all(); -#else - unsigned long long set, way; - unsigned long mm_asid = mm->context & MMU_CONTEXT_ASID_MASK; - for (set = 0; set < cpu_data->dcache.sets; set++) { - unsigned long long set_base_config_addr = CACHE_OC_ADDRESS_ARRAY + (set << cpu_data->dcache.set_shift); - for (way = 0; way < cpu_data->dcache.ways; way++) { - unsigned long long config_addr = set_base_config_addr + (way << cpu_data->dcache.way_step_shift); - unsigned long long tag0; - unsigned long line_valid; - - asm __volatile__("getcfg %1, 0, %0" : "=r" (tag0) : "r" (config_addr)); - line_valid = tag0 & SH_CACHE_VALID; - if (line_valid) { - unsigned long cache_asid; - unsigned long epn; - - cache_asid = (tag0 & cpu_data->dcache.asid_mask) >> cpu_data->dcache.asid_shift; - /* The next line needs some - explanation. The virtual tags - encode bits [31:13] of the virtual - address, bit [12] of the 'tag' being - implied by the cache set index. */ - epn = (tag0 & cpu_data->dcache.epn_mask) | ((set & 0x80) << cpu_data->dcache.entry_shift); - - if ((cache_asid == mm_asid) && (start <= epn) && (epn < end)) { - /* TODO : could optimise this - call by batching multiple - adjacent sets together. */ - sh64_dcache_purge_sets(set, 1); - break; /* Don't waste time inspecting other ways for this set */ - } - } - } - } -#endif - } else { - /* Small range, covered by a single page table page */ - start &= PAGE_MASK; /* should already be so */ - end = PAGE_ALIGN(end); /* should already be so */ - sh64_dcache_purge_user_pages(mm, start, end); - } - return; -} - -static void sh64_dcache_wback_current_user_range(unsigned long start, unsigned long end) -{ - unsigned long long aligned_start; - unsigned long long ull_end; - unsigned long long addr; - - ull_end = end; - - /* Just wback over the range using the natural addresses. TLB miss - handling will be OK (TBC) : the range has just been written to by - the signal frame setup code, so the PTEs must exist. - - Note, if we have CONFIG_PREEMPT and get preempted inside this loop, - it doesn't matter, even if the pid->ASID mapping changes whilst - we're away. In that case the cache will have been flushed when the - mapping was renewed. So the writebacks below will be nugatory (and - we'll doubtless have to fault the TLB entry/ies in again with the - new ASID), but it's a rare case. - */ - aligned_start = start & L1_CACHE_ALIGN_MASK; - addr = aligned_start; - while (addr < ull_end) { - asm __volatile__ ("ocbwb %0, 0" : : "r" (addr)); - addr += L1_CACHE_BYTES; - } -} - -/****************************************************************************/ - -/* These *MUST* lie in an area of virtual address space that's otherwise unused. */ -#define UNIQUE_EADDR_START 0xe0000000UL -#define UNIQUE_EADDR_END 0xe8000000UL - -static unsigned long sh64_make_unique_eaddr(unsigned long user_eaddr, unsigned long paddr) -{ - /* Given a physical address paddr, and a user virtual address - user_eaddr which will eventually be mapped to it, create a one-off - kernel-private eaddr mapped to the same paddr. This is used for - creating special destination pages for copy_user_page and - clear_user_page */ - - static unsigned long current_pointer = UNIQUE_EADDR_START; - unsigned long coloured_pointer; - - if (current_pointer == UNIQUE_EADDR_END) { - sh64_dcache_purge_all(); - current_pointer = UNIQUE_EADDR_START; - } - - coloured_pointer = (current_pointer & ~CACHE_OC_SYN_MASK) | (user_eaddr & CACHE_OC_SYN_MASK); - sh64_setup_dtlb_cache_slot(coloured_pointer, get_asid(), paddr); - - current_pointer += (PAGE_SIZE << CACHE_OC_N_SYNBITS); - - return coloured_pointer; -} - -/****************************************************************************/ - -static void sh64_copy_user_page_coloured(void *to, void *from, unsigned long address) -{ - void *coloured_to; - - /* Discard any existing cache entries of the wrong colour. These are - present quite often, if the kernel has recently used the page - internally, then given it up, then it's been allocated to the user. - */ - sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); - - coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); - sh64_page_copy(from, coloured_to); - - sh64_teardown_dtlb_cache_slot(); -} - -static void sh64_clear_user_page_coloured(void *to, unsigned long address) -{ - void *coloured_to; - - /* Discard any existing kernel-originated lines of the wrong colour (as - above) */ - sh64_dcache_purge_coloured_phy_page(__pa(to), (unsigned long) to); - - coloured_to = (void *) sh64_make_unique_eaddr(address, __pa(to)); - sh64_page_clear(coloured_to); - - sh64_teardown_dtlb_cache_slot(); -} - -#endif /* !CONFIG_DCACHE_DISABLED */ - -/****************************************************************************/ - -/*########################################################################## - EXTERNALLY CALLABLE API. - ##########################################################################*/ - -/* These functions are described in Documentation/cachetlb.txt. - Each one of these functions varies in behaviour depending on whether the - I-cache and/or D-cache are configured out. - - Note that the Linux term 'flush' corresponds to what is termed 'purge' in - the sh/sh64 jargon for the D-cache, i.e. write back dirty data then - invalidate the cache lines, and 'invalidate' for the I-cache. - */ - -#undef FLUSH_TRACE - -void flush_cache_all(void) -{ - /* Invalidate the entire contents of both caches, after writing back to - memory any dirty data from the D-cache. */ - sh64_dcache_purge_all(); - sh64_icache_inv_all(); -} - -/****************************************************************************/ - -void flush_cache_mm(struct mm_struct *mm) -{ - /* Invalidate an entire user-address space from both caches, after - writing back dirty data (e.g. for shared mmap etc). */ - - /* This could be coded selectively by inspecting all the tags then - doing 4*alloco on any set containing a match (as for - flush_cache_range), but fork/exit/execve (where this is called from) - are expensive anyway. */ - - /* Have to do a purge here, despite the comments re I-cache below. - There could be odd-coloured dirty data associated with the mm still - in the cache - if this gets written out through natural eviction - after the kernel has reused the page there will be chaos. - */ - - sh64_dcache_purge_all(); - - /* The mm being torn down won't ever be active again, so any Icache - lines tagged with its ASID won't be visible for the rest of the - lifetime of this ASID cycle. Before the ASID gets reused, there - will be a flush_cache_all. Hence we don't need to touch the - I-cache. This is similar to the lack of action needed in - flush_tlb_mm - see fault.c. */ -} - -/****************************************************************************/ - -void flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - struct mm_struct *mm = vma->vm_mm; - - /* Invalidate (from both caches) the range [start,end) of virtual - addresses from the user address space specified by mm, after writing - back any dirty data. - - Note, 'end' is 1 byte beyond the end of the range to flush. */ - - sh64_dcache_purge_user_range(mm, start, end); - sh64_icache_inv_user_page_range(mm, start, end); -} - -/****************************************************************************/ - -void flush_cache_page(struct vm_area_struct *vma, unsigned long eaddr, unsigned long pfn) -{ - /* Invalidate any entries in either cache for the vma within the user - address space vma->vm_mm for the page starting at virtual address - 'eaddr'. This seems to be used primarily in breaking COW. Note, - the I-cache must be searched too in case the page in question is - both writable and being executed from (e.g. stack trampolines.) - - Note, this is called with pte lock held. - */ - - sh64_dcache_purge_phy_page(pfn << PAGE_SHIFT); - - if (vma->vm_flags & VM_EXEC) { - sh64_icache_inv_user_page(vma, eaddr); - } -} - -/****************************************************************************/ - -#ifndef CONFIG_DCACHE_DISABLED - -void copy_user_page(void *to, void *from, unsigned long address, struct page *page) -{ - /* 'from' and 'to' are kernel virtual addresses (within the superpage - mapping of the physical RAM). 'address' is the user virtual address - where the copy 'to' will be mapped after. This allows a custom - mapping to be used to ensure that the new copy is placed in the - right cache sets for the user to see it without having to bounce it - out via memory. Note however : the call to flush_page_to_ram in - (generic)/mm/memory.c:(break_cow) undoes all this good work in that one - very important case! - - TBD : can we guarantee that on every call, any cache entries for - 'from' are in the same colour sets as 'address' also? i.e. is this - always used just to deal with COW? (I suspect not). */ - - /* There are two possibilities here for when the page 'from' was last accessed: - * by the kernel : this is OK, no purge required. - * by the/a user (e.g. for break_COW) : need to purge. - - If the potential user mapping at 'address' is the same colour as - 'from' there is no need to purge any cache lines from the 'from' - page mapped into cache sets of colour 'address'. (The copy will be - accessing the page through 'from'). - */ - - if (((address ^ (unsigned long) from) & CACHE_OC_SYN_MASK) != 0) { - sh64_dcache_purge_coloured_phy_page(__pa(from), address); - } - - if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { - /* No synonym problem on destination */ - sh64_page_copy(from, to); - } else { - sh64_copy_user_page_coloured(to, from, address); - } - - /* Note, don't need to flush 'from' page from the cache again - it's - done anyway by the generic code */ -} - -void clear_user_page(void *to, unsigned long address, struct page *page) -{ - /* 'to' is a kernel virtual address (within the superpage - mapping of the physical RAM). 'address' is the user virtual address - where the 'to' page will be mapped after. This allows a custom - mapping to be used to ensure that the new copy is placed in the - right cache sets for the user to see it without having to bounce it - out via memory. - */ - - if (((address ^ (unsigned long) to) & CACHE_OC_SYN_MASK) == 0) { - /* No synonym problem on destination */ - sh64_page_clear(to); - } else { - sh64_clear_user_page_coloured(to, address); - } -} - -#endif /* !CONFIG_DCACHE_DISABLED */ - -/****************************************************************************/ - -void flush_dcache_page(struct page *page) -{ - sh64_dcache_purge_phy_page(page_to_phys(page)); - wmb(); -} - -/****************************************************************************/ - -void flush_icache_range(unsigned long start, unsigned long end) -{ - /* Flush the range [start,end] of kernel virtual adddress space from - the I-cache. The corresponding range must be purged from the - D-cache also because the SH-5 doesn't have cache snooping between - the caches. The addresses will be visible through the superpage - mapping, therefore it's guaranteed that there no cache entries for - the range in cache sets of the wrong colour. - - Primarily used for cohering the I-cache after a module has - been loaded. */ - - /* We also make sure to purge the same range from the D-cache since - flush_page_to_ram() won't be doing this for us! */ - - sh64_dcache_purge_kernel_range(start, end); - wmb(); - sh64_icache_inv_kernel_range(start, end); -} - -/****************************************************************************/ - -void flush_icache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long addr, int len) -{ - /* Flush the range of user (defined by vma->vm_mm) address space - starting at 'addr' for 'len' bytes from the cache. The range does - not straddle a page boundary, the unique physical page containing - the range is 'page'. This seems to be used mainly for invalidating - an address range following a poke into the program text through the - ptrace() call from another process (e.g. for BRK instruction - insertion). */ - - sh64_dcache_purge_coloured_phy_page(page_to_phys(page), addr); - mb(); - - if (vma->vm_flags & VM_EXEC) { - sh64_icache_inv_user_small_range(vma->vm_mm, addr, len); - } -} - -/*########################################################################## - ARCH/SH64 PRIVATE CALLABLE API. - ##########################################################################*/ - -void flush_cache_sigtramp(unsigned long start, unsigned long end) -{ - /* For the address range [start,end), write back the data from the - D-cache and invalidate the corresponding region of the I-cache for - the current process. Used to flush signal trampolines on the stack - to make them executable. */ - - sh64_dcache_wback_current_user_range(start, end); - wmb(); - sh64_icache_inv_current_user_range(start, end); -} - diff -puN arch/sh64/mm/consistent.c~git-sh /dev/null --- a/arch/sh64/mm/consistent.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) - * Copyright (C) 2003 Paul Mundt (lethal@linux-sh.org) - * - * May be copied or modified under the terms of the GNU General Public - * License. See linux/COPYING for more information. - * - * Dynamic DMA mapping support. - */ -#include -#include -#include -#include -#include -#include -#include - -void *consistent_alloc(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC; - void *vp; - - if (hwdev == NULL || hwdev->dma_mask != 0xffffffff) - gfp |= GFP_DMA; - - ret = (void *)__get_free_pages(gfp, get_order(size)); - - /* now call our friend ioremap_nocache to give us an uncached area */ - vp = ioremap_nocache(virt_to_phys(ret), size); - - if (vp != NULL) { - memset(vp, 0, size); - *dma_handle = virt_to_phys(ret); - dma_cache_sync(NULL, ret, size, DMA_BIDIRECTIONAL); - } - - return vp; -} -EXPORT_SYMBOL(consistent_alloc); - -void consistent_free(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - void *alloc; - - alloc = phys_to_virt((unsigned long)dma_handle); - free_pages((unsigned long)alloc, get_order(size)); - - iounmap(vaddr); -} -EXPORT_SYMBOL(consistent_free); diff -puN arch/sh64/mm/extable.c~git-sh /dev/null --- a/arch/sh64/mm/extable.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/extable.c - * - * Copyright (C) 2003 Richard Curnow - * Copyright (C) 2003, 2004 Paul Mundt - * - * Cloned from the 2.5 SH version.. - */ -#include -#include -#include - -extern unsigned long copy_user_memcpy, copy_user_memcpy_end; -extern void __copy_user_fixup(void); - -static const struct exception_table_entry __copy_user_fixup_ex = { - .fixup = (unsigned long)&__copy_user_fixup, -}; - -/* Some functions that may trap due to a bad user-mode address have too many loads - and stores in them to make it at all practical to label each one and put them all in - the main exception table. - - In particular, the fast memcpy routine is like this. It's fix-up is just to fall back - to a slow byte-at-a-time copy, which is handled the conventional way. So it's functionally - OK to just handle any trap occurring in the fast memcpy with that fixup. */ -static const struct exception_table_entry *check_exception_ranges(unsigned long addr) -{ - if ((addr >= (unsigned long)©_user_memcpy) && - (addr <= (unsigned long)©_user_memcpy_end)) - return &__copy_user_fixup_ex; - - return NULL; -} - -/* Simple binary search */ -const struct exception_table_entry * -search_extable(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) -{ - const struct exception_table_entry *mid; - - mid = check_exception_ranges(value); - if (mid) - return mid; - - while (first <= last) { - long diff; - - mid = (last - first) / 2 + first; - diff = mid->insn - value; - if (diff == 0) - return mid; - else if (diff < 0) - first = mid+1; - else - last = mid-1; - } - - return NULL; -} - -int fixup_exception(struct pt_regs *regs) -{ - const struct exception_table_entry *fixup; - - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return 1; - } - - return 0; -} - diff -puN arch/sh64/mm/fault.c~git-sh /dev/null --- a/arch/sh64/mm/fault.c +++ /dev/null @@ -1,602 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/fault.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Richard Curnow (/proc/tlb, bug fixes) - * Copyright (C) 2003 Paul Mundt - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include /* required by inline asm statements */ - -#if defined(CONFIG_SH64_PROC_TLB) -#include -#include -/* Count numbers of tlb refills in each region */ -static unsigned long long calls_to_update_mmu_cache = 0ULL; -static unsigned long long calls_to_flush_tlb_page = 0ULL; -static unsigned long long calls_to_flush_tlb_range = 0ULL; -static unsigned long long calls_to_flush_tlb_mm = 0ULL; -static unsigned long long calls_to_flush_tlb_all = 0ULL; -unsigned long long calls_to_do_slow_page_fault = 0ULL; -unsigned long long calls_to_do_fast_page_fault = 0ULL; - -/* Count size of ranges for flush_tlb_range */ -static unsigned long long flush_tlb_range_1 = 0ULL; -static unsigned long long flush_tlb_range_2 = 0ULL; -static unsigned long long flush_tlb_range_3_4 = 0ULL; -static unsigned long long flush_tlb_range_5_7 = 0ULL; -static unsigned long long flush_tlb_range_8_11 = 0ULL; -static unsigned long long flush_tlb_range_12_15 = 0ULL; -static unsigned long long flush_tlb_range_16_up = 0ULL; - -static unsigned long long page_not_present = 0ULL; - -#endif - -extern void die(const char *,struct pt_regs *,long); - -#define PFLAG(val,flag) (( (val) & (flag) ) ? #flag : "" ) -#define PPROT(flag) PFLAG(pgprot_val(prot),flag) - -static inline void print_prots(pgprot_t prot) -{ - printk("prot is 0x%08lx\n",pgprot_val(prot)); - - printk("%s %s %s %s %s\n",PPROT(_PAGE_SHARED),PPROT(_PAGE_READ), - PPROT(_PAGE_EXECUTE),PPROT(_PAGE_WRITE),PPROT(_PAGE_USER)); -} - -static inline void print_vma(struct vm_area_struct *vma) -{ - printk("vma start 0x%08lx\n", vma->vm_start); - printk("vma end 0x%08lx\n", vma->vm_end); - - print_prots(vma->vm_page_prot); - printk("vm_flags 0x%08lx\n", vma->vm_flags); -} - -static inline void print_task(struct task_struct *tsk) -{ - printk("Task pid %d\n", task_pid_nr(tsk)); -} - -static pte_t *lookup_pte(struct mm_struct *mm, unsigned long address) -{ - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - - dir = pgd_offset(mm, address); - if (pgd_none(*dir)) { - return NULL; - } - - pmd = pmd_offset(dir, address); - if (pmd_none(*pmd)) { - return NULL; - } - - pte = pte_offset_kernel(pmd, address); - entry = *pte; - - if (pte_none(entry)) { - return NULL; - } - if (!pte_present(entry)) { - return NULL; - } - - return pte; -} - -/* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate - * routines. - */ -asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long writeaccess, - unsigned long textaccess, unsigned long address) -{ - struct task_struct *tsk; - struct mm_struct *mm; - struct vm_area_struct * vma; - const struct exception_table_entry *fixup; - pte_t *pte; - int fault; - -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_do_slow_page_fault; -#endif - - /* SIM - * Note this is now called with interrupts still disabled - * This is to cope with being called for a missing IO port - * address with interrupts disabled. This should be fixed as - * soon as we have a better 'fast path' miss handler. - * - * Plus take care how you try and debug this stuff. - * For example, writing debug data to a port which you - * have just faulted on is not going to work. - */ - - tsk = current; - mm = tsk->mm; - - /* Not an IO address, so reenable interrupts */ - local_irq_enable(); - - /* - * If we're in an interrupt or have no user - * context, we must not take the fault.. - */ - if (in_atomic() || !mm) - goto no_context; - - /* TLB misses upon some cache flushes get done under cli() */ - down_read(&mm->mmap_sem); - - vma = find_vma(mm, address); - - if (!vma) { -#ifdef DEBUG_FAULT - print_task(tsk); - printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", - __FUNCTION__,__LINE__, - address,regs->pc,textaccess,writeaccess); - show_regs(regs); -#endif - goto bad_area; - } - if (vma->vm_start <= address) { - goto good_area; - } - - if (!(vma->vm_flags & VM_GROWSDOWN)) { -#ifdef DEBUG_FAULT - print_task(tsk); - printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", - __FUNCTION__,__LINE__, - address,regs->pc,textaccess,writeaccess); - show_regs(regs); - - print_vma(vma); -#endif - goto bad_area; - } - if (expand_stack(vma, address)) { -#ifdef DEBUG_FAULT - print_task(tsk); - printk("%s:%d fault, address is 0x%08x PC %016Lx textaccess %d writeaccess %d\n", - __FUNCTION__,__LINE__, - address,regs->pc,textaccess,writeaccess); - show_regs(regs); -#endif - goto bad_area; - } -/* - * Ok, we have a good vm_area for this memory access, so - * we can handle it.. - */ -good_area: - if (textaccess) { - if (!(vma->vm_flags & VM_EXEC)) - goto bad_area; - } else { - if (writeaccess) { - if (!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { - if (!(vma->vm_flags & VM_READ)) - goto bad_area; - } - } - - /* - * If for any reason at all we couldn't handle the fault, - * make sure we exit gracefully rather than endlessly redo - * the fault. - */ -survive: - fault = handle_mm_fault(mm, vma, address, writeaccess); - 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) - tsk->maj_flt++; - else - tsk->min_flt++; - - /* If we get here, the page fault has been handled. Do the TLB refill - now from the newly-setup PTE, to avoid having to fault again right - away on the same instruction. */ - pte = lookup_pte (mm, address); - if (!pte) { - /* From empirical evidence, we can get here, due to - !pte_present(pte). (e.g. if a swap-in occurs, and the page - is swapped back out again before the process that wanted it - gets rescheduled?) */ - goto no_pte; - } - - __do_tlb_refill(address, textaccess, pte); - -no_pte: - - up_read(&mm->mmap_sem); - return; - -/* - * Something tried to access memory that isn't in our memory map.. - * Fix it, but check if it's kernel or user first.. - */ -bad_area: -#ifdef DEBUG_FAULT - printk("fault:bad area\n"); -#endif - up_read(&mm->mmap_sem); - - if (user_mode(regs)) { - static int count=0; - siginfo_t info; - if (count < 4) { - /* This is really to help debug faults when starting - * usermode, so only need a few */ - count++; - printk("user mode bad_area address=%08lx pid=%d (%s) pc=%08lx\n", - address, task_pid_nr(current), current->comm, - (unsigned long) regs->pc); -#if 0 - show_regs(regs); -#endif - } - if (is_global_init(tsk)) { - panic("INIT had user mode bad_area\n"); - } - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_addr = (void *) address; - force_sig_info(SIGSEGV, &info, tsk); - return; - } - -no_context: -#ifdef DEBUG_FAULT - printk("fault:No context\n"); -#endif - /* Are we prepared to handle this kernel fault? */ - fixup = search_exception_tables(regs->pc); - if (fixup) { - regs->pc = fixup->fixup; - return; - } - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - * - */ - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); - else - printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n", address); - printk(KERN_ALERT "pc = %08Lx%08Lx\n", regs->pc >> 32, regs->pc & 0xffffffff); - die("Oops", regs, writeaccess); - do_exit(SIGKILL); - -/* - * We ran out of memory, or some other thing happened to us that made - * us unable to handle the page fault gracefully. - */ -out_of_memory: - if (is_global_init(current)) { - panic("INIT out of memory\n"); - yield(); - goto survive; - } - printk("fault:Out of memory\n"); - up_read(&mm->mmap_sem); - if (is_global_init(current)) { - yield(); - down_read(&mm->mmap_sem); - goto survive; - } - printk("VM: killing process %s\n", tsk->comm); - if (user_mode(regs)) - do_group_exit(SIGKILL); - goto no_context; - -do_sigbus: - printk("fault:Do sigbus\n"); - up_read(&mm->mmap_sem); - - /* - * Send a sigbus, regardless of whether we were in kernel - * or user mode. - */ - tsk->thread.address = address; - tsk->thread.error_code = writeaccess; - tsk->thread.trap_no = 14; - force_sig(SIGBUS, tsk); - - /* Kernel mode? Handle exceptions or die */ - if (!user_mode(regs)) - goto no_context; -} - - -void flush_tlb_all(void); - -void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte) -{ -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_update_mmu_cache; -#endif - - /* - * This appears to get called once for every pte entry that gets - * established => I don't think it's efficient to try refilling the - * TLBs with the pages - some may not get accessed even. Also, for - * executable pages, it is impossible to determine reliably here which - * TLB they should be mapped into (or both even). - * - * So, just do nothing here and handle faults on demand. In the - * TLBMISS handling case, the refill is now done anyway after the pte - * has been fixed up, so that deals with most useful cases. - */ -} - -static void __flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - unsigned long long match, pteh=0, lpage; - unsigned long tlb; - struct mm_struct *mm; - - mm = vma->vm_mm; - - if (mm->context == NO_CONTEXT) - return; - - /* - * Sign-extend based on neff. - */ - lpage = (page & NEFF_SIGN) ? (page | NEFF_MASK) : page; - match = ((mm->context & MMU_CONTEXT_ASID_MASK) << PTEH_ASID_SHIFT) | PTEH_VALID; - match |= lpage; - - /* Do ITLB : don't bother for pages in non-exectutable VMAs */ - if (vma->vm_flags & VM_EXEC) { - for_each_itlb_entry(tlb) { - asm volatile ("getcfg %1, 0, %0" - : "=r" (pteh) - : "r" (tlb) ); - - if (pteh == match) { - __flush_tlb_slot(tlb); - break; - } - - } - } - - /* Do DTLB : any page could potentially be in here. */ - for_each_dtlb_entry(tlb) { - asm volatile ("getcfg %1, 0, %0" - : "=r" (pteh) - : "r" (tlb) ); - - if (pteh == match) { - __flush_tlb_slot(tlb); - break; - } - - } -} - -void flush_tlb_page(struct vm_area_struct *vma, unsigned long page) -{ - unsigned long flags; - -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_flush_tlb_page; -#endif - - if (vma->vm_mm) { - page &= PAGE_MASK; - local_irq_save(flags); - __flush_tlb_page(vma, page); - local_irq_restore(flags); - } -} - -void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end) -{ - unsigned long flags; - unsigned long long match, pteh=0, pteh_epn, pteh_low; - unsigned long tlb; - struct mm_struct *mm; - - mm = vma->vm_mm; - -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_flush_tlb_range; - - { - unsigned long size = (end - 1) - start; - size >>= 12; /* divide by PAGE_SIZE */ - size++; /* end=start+4096 => 1 page */ - switch (size) { - case 1 : flush_tlb_range_1++; break; - case 2 : flush_tlb_range_2++; break; - case 3 ... 4 : flush_tlb_range_3_4++; break; - case 5 ... 7 : flush_tlb_range_5_7++; break; - case 8 ... 11 : flush_tlb_range_8_11++; break; - case 12 ... 15 : flush_tlb_range_12_15++; break; - default : flush_tlb_range_16_up++; break; - } - } -#endif - - if (mm->context == NO_CONTEXT) - return; - - local_irq_save(flags); - - start &= PAGE_MASK; - end &= PAGE_MASK; - - match = ((mm->context & MMU_CONTEXT_ASID_MASK) << PTEH_ASID_SHIFT) | PTEH_VALID; - - /* Flush ITLB */ - for_each_itlb_entry(tlb) { - asm volatile ("getcfg %1, 0, %0" - : "=r" (pteh) - : "r" (tlb) ); - - pteh_epn = pteh & PAGE_MASK; - pteh_low = pteh & ~PAGE_MASK; - - if (pteh_low == match && pteh_epn >= start && pteh_epn <= end) - __flush_tlb_slot(tlb); - } - - /* Flush DTLB */ - for_each_dtlb_entry(tlb) { - asm volatile ("getcfg %1, 0, %0" - : "=r" (pteh) - : "r" (tlb) ); - - pteh_epn = pteh & PAGE_MASK; - pteh_low = pteh & ~PAGE_MASK; - - if (pteh_low == match && pteh_epn >= start && pteh_epn <= end) - __flush_tlb_slot(tlb); - } - - local_irq_restore(flags); -} - -void flush_tlb_mm(struct mm_struct *mm) -{ - unsigned long flags; - -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_flush_tlb_mm; -#endif - - if (mm->context == NO_CONTEXT) - return; - - local_irq_save(flags); - - mm->context=NO_CONTEXT; - if(mm==current->mm) - activate_context(mm); - - local_irq_restore(flags); - -} - -void flush_tlb_all(void) -{ - /* Invalidate all, including shared pages, excluding fixed TLBs */ - - unsigned long flags, tlb; - -#if defined(CONFIG_SH64_PROC_TLB) - ++calls_to_flush_tlb_all; -#endif - - local_irq_save(flags); - - /* Flush each ITLB entry */ - for_each_itlb_entry(tlb) { - __flush_tlb_slot(tlb); - } - - /* Flush each DTLB entry */ - for_each_dtlb_entry(tlb) { - __flush_tlb_slot(tlb); - } - - local_irq_restore(flags); -} - -void flush_tlb_kernel_range(unsigned long start, unsigned long end) -{ - /* FIXME: Optimize this later.. */ - flush_tlb_all(); -} - -#if defined(CONFIG_SH64_PROC_TLB) -/* Procfs interface to read the performance information */ - -static int -tlb_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, void *data) -{ - int len=0; - len += sprintf(buf+len, "do_fast_page_fault called %12lld times\n", calls_to_do_fast_page_fault); - len += sprintf(buf+len, "do_slow_page_fault called %12lld times\n", calls_to_do_slow_page_fault); - len += sprintf(buf+len, "update_mmu_cache called %12lld times\n", calls_to_update_mmu_cache); - len += sprintf(buf+len, "flush_tlb_page called %12lld times\n", calls_to_flush_tlb_page); - len += sprintf(buf+len, "flush_tlb_range called %12lld times\n", calls_to_flush_tlb_range); - len += sprintf(buf+len, "flush_tlb_mm called %12lld times\n", calls_to_flush_tlb_mm); - len += sprintf(buf+len, "flush_tlb_all called %12lld times\n", calls_to_flush_tlb_all); - len += sprintf(buf+len, "flush_tlb_range_sizes\n" - " 1 : %12lld\n" - " 2 : %12lld\n" - " 3 - 4 : %12lld\n" - " 5 - 7 : %12lld\n" - " 8 - 11 : %12lld\n" - "12 - 15 : %12lld\n" - "16+ : %12lld\n", - flush_tlb_range_1, flush_tlb_range_2, flush_tlb_range_3_4, - flush_tlb_range_5_7, flush_tlb_range_8_11, flush_tlb_range_12_15, - flush_tlb_range_16_up); - len += sprintf(buf+len, "page not present %12lld times\n", page_not_present); - *eof = 1; - return len; -} - -static int __init register_proc_tlb(void) -{ - create_proc_read_entry("tlb", 0, NULL, tlb_proc_info, NULL); - return 0; -} - -__initcall(register_proc_tlb); - -#endif diff -puN arch/sh64/mm/hugetlbpage.c~git-sh /dev/null --- a/arch/sh64/mm/hugetlbpage.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * arch/sh64/mm/hugetlbpage.c - * - * SuperH HugeTLB page support. - * - * Cloned from sparc64 by Paul Mundt. - * - * Copyright (C) 2002, 2003 David S. Miller (davem@redhat.com) - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte = NULL; - - pgd = pgd_offset(mm, addr); - if (pgd) { - pmd = pmd_alloc(mm, pgd, addr); - if (pmd) - pte = pte_alloc_map(mm, pmd, addr); - } - return pte; -} - -pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr) -{ - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte = NULL; - - pgd = pgd_offset(mm, addr); - if (pgd) { - pmd = pmd_offset(pgd, addr); - if (pmd) - pte = pte_offset_map(pmd, addr); - } - return pte; -} - -int huge_pmd_unshare(struct mm_struct *mm, unsigned long *addr, pte_t *ptep) -{ - return 0; -} - -void set_huge_pte_at(struct mm_struct *mm, unsigned long addr, - pte_t *ptep, pte_t entry) -{ - int i; - - for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { - set_pte_at(mm, addr, ptep, entry); - ptep++; - addr += PAGE_SIZE; - pte_val(entry) += PAGE_SIZE; - } -} - -pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, - pte_t *ptep) -{ - pte_t entry; - int i; - - entry = *ptep; - - for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) { - pte_clear(mm, addr, ptep); - addr += PAGE_SIZE; - ptep++; - } - - return entry; -} - -struct page *follow_huge_addr(struct mm_struct *mm, - unsigned long address, int write) -{ - return ERR_PTR(-EINVAL); -} - -int pmd_huge(pmd_t pmd) -{ - return 0; -} - -struct page *follow_huge_pmd(struct mm_struct *mm, unsigned long address, - pmd_t *pmd, int write) -{ - return NULL; -} diff -puN arch/sh64/mm/init.c~git-sh /dev/null --- a/arch/sh64/mm/init.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/init.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - -/* - * Cache of MMU context last used. - */ -unsigned long mmu_context_cache; -pgd_t * mmu_pdtp_cache; -int after_bootmem = 0; - -/* - * BAD_PAGE is the page that is used for page faults when linux - * is out-of-memory. Older versions of linux just did a - * do_exit(), but using this instead means there is less risk - * for a process dying in kernel mode, possibly leaving an inode - * unused etc.. - * - * BAD_PAGETABLE is the accompanying page-table: it is initialized - * to point to BAD_PAGE entries. - * - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ - -extern unsigned char empty_zero_page[PAGE_SIZE]; -extern unsigned char empty_bad_page[PAGE_SIZE]; -extern pte_t empty_bad_pte_table[PTRS_PER_PTE]; -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; - -extern char _text, _etext, _edata, __bss_start, _end; -extern char __init_begin, __init_end; - -/* It'd be good if these lines were in the standard header file. */ -#define START_PFN (NODE_DATA(0)->bdata->node_boot_start >> PAGE_SHIFT) -#define MAX_LOW_PFN (NODE_DATA(0)->bdata->node_low_pfn) - - -void show_mem(void) -{ - int i, total = 0, reserved = 0; - int shared = 0, cached = 0; - - printk("Mem-info:\n"); - show_free_areas(); - printk("Free swap: %6ldkB\n",nr_swap_pages<<(PAGE_SHIFT-10)); - i = max_mapnr; - while (i-- > 0) { - total++; - if (PageReserved(mem_map+i)) - reserved++; - else if (PageSwapCache(mem_map+i)) - cached++; - else if (page_count(mem_map+i)) - shared += page_count(mem_map+i) - 1; - } - printk("%d pages of RAM\n",total); - printk("%d reserved pages\n",reserved); - printk("%d pages shared\n",shared); - printk("%d pages swap cached\n",cached); - printk("%ld pages in page table cache\n", quicklist_total_size()); -} - -/* - * paging_init() sets up the page tables. - * - * head.S already did a lot to set up address translation for the kernel. - * Here we comes with: - * . MMU enabled - * . ASID set (SR) - * . some 512MB regions being mapped of which the most relevant here is: - * . CACHED segment (ASID 0 [irrelevant], shared AND NOT user) - * . possible variable length regions being mapped as: - * . UNCACHED segment (ASID 0 [irrelevant], shared AND NOT user) - * . All of the memory regions are placed, independently from the platform - * on high addresses, above 0x80000000. - * . swapper_pg_dir is already cleared out by the .space directive - * in any case swapper does not require a real page directory since - * it's all kernel contained. - * - * Those pesky NULL-reference errors in the kernel are then - * dealt with by not mapping address 0x00000000 at all. - * - */ -void __init paging_init(void) -{ - unsigned long zones_size[MAX_NR_ZONES] = {0, }; - - pgd_init((unsigned long)swapper_pg_dir); - pgd_init((unsigned long)swapper_pg_dir + - sizeof(pgd_t) * USER_PTRS_PER_PGD); - - mmu_context_cache = MMU_CONTEXT_FIRST_VERSION; - - zones_size[ZONE_NORMAL] = MAX_LOW_PFN - START_PFN; - NODE_DATA(0)->node_mem_map = NULL; - free_area_init_node(0, NODE_DATA(0), zones_size, __MEMORY_START >> PAGE_SHIFT, 0); -} - -void __init mem_init(void) -{ - int codesize, reservedpages, datasize, initsize; - int tmp; - - max_mapnr = num_physpages = MAX_LOW_PFN - START_PFN; - high_memory = (void *)__va(MAX_LOW_PFN * PAGE_SIZE); - - /* - * Clear the zero-page. - * This is not required but we might want to re-use - * this very page to pass boot parameters, one day. - */ - memset(empty_zero_page, 0, PAGE_SIZE); - - /* this will put all low memory onto the freelists */ - totalram_pages += free_all_bootmem_node(NODE_DATA(0)); - reservedpages = 0; - for (tmp = 0; tmp < num_physpages; tmp++) - /* - * Only count reserved RAM pages - */ - if (PageReserved(mem_map+tmp)) - reservedpages++; - - after_bootmem = 1; - - codesize = (unsigned long) &_etext - (unsigned long) &_text; - datasize = (unsigned long) &_edata - (unsigned long) &_etext; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - printk("Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", - (unsigned long) nr_free_pages() << (PAGE_SHIFT-10), - max_mapnr << (PAGE_SHIFT-10), - codesize >> 10, - reservedpages << (PAGE_SHIFT-10), - datasize >> 10, - initsize >> 10); -} - -void free_initmem(void) -{ - unsigned long addr; - - addr = (unsigned long)(&__init_begin); - for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { - ClearPageReserved(virt_to_page(addr)); - init_page_count(virt_to_page(addr)); - free_page(addr); - totalram_pages++; - } - printk ("Freeing unused kernel memory: %ldk freed\n", (&__init_end - &__init_begin) >> 10); -} - -#ifdef CONFIG_BLK_DEV_INITRD -void free_initrd_mem(unsigned long start, unsigned long end) -{ - unsigned long p; - for (p = start; p < end; p += PAGE_SIZE) { - ClearPageReserved(virt_to_page(p)); - init_page_count(virt_to_page(p)); - free_page(p); - totalram_pages++; - } - printk ("Freeing initrd memory: %ldk freed\n", (end - start) >> 10); -} -#endif - diff -puN arch/sh64/mm/ioremap.c~git-sh /dev/null --- a/arch/sh64/mm/ioremap.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/ioremap.c - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * Mostly derived from arch/sh/mm/ioremap.c which, in turn is mostly - * derived from arch/i386/mm/ioremap.c . - * - * (C) Copyright 1995 1996 Linus Torvalds - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static void shmedia_mapioaddr(unsigned long, unsigned long); -static unsigned long shmedia_ioremap(struct resource *, u32, int); - -/* - * Generic mapping function (not visible outside): - */ - -/* - * Remap an arbitrary physical address space into the kernel virtual - * address space. Needed when the kernel wants to access high addresses - * directly. - * - * NOTE! We need to allow non-page-aligned mappings too: we will obviously - * have to convert them into an offset in a page-aligned mapping, but the - * caller shouldn't need to know that small detail. - */ -void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags) -{ - void * addr; - struct vm_struct * area; - unsigned long offset, last_addr; - pgprot_t pgprot; - - /* Don't allow wraparound or zero size */ - last_addr = phys_addr + size - 1; - if (!size || last_addr < phys_addr) - return NULL; - - pgprot = __pgprot(_PAGE_PRESENT | _PAGE_READ | - _PAGE_WRITE | _PAGE_DIRTY | - _PAGE_ACCESSED | _PAGE_SHARED | flags); - - /* - * Mappings have to be page-aligned - */ - offset = phys_addr & ~PAGE_MASK; - phys_addr &= PAGE_MASK; - size = PAGE_ALIGN(last_addr + 1) - phys_addr; - - /* - * Ok, go for it.. - */ - area = get_vm_area(size, VM_IOREMAP); - pr_debug("Get vm_area returns %p addr %p\n",area,area->addr); - if (!area) - return NULL; - area->phys_addr = phys_addr; - addr = area->addr; - if (ioremap_page_range((unsigned long)addr, (unsigned long)addr + size, - phys_addr, pgprot)) { - vunmap(addr); - return NULL; - } - return (void *) (offset + (char *)addr); -} -EXPORT_SYMBOL(__ioremap); - -void iounmap(void *addr) -{ - struct vm_struct *area; - - vfree((void *) (PAGE_MASK & (unsigned long) addr)); - area = remove_vm_area((void *) (PAGE_MASK & (unsigned long) addr)); - if (!area) { - printk(KERN_ERR "iounmap: bad address %p\n", addr); - return; - } - - kfree(area); -} -EXPORT_SYMBOL(iounmap); - -static struct resource shmedia_iomap = { - .name = "shmedia_iomap", - .start = IOBASE_VADDR + PAGE_SIZE, - .end = IOBASE_END - 1, -}; - -static void shmedia_mapioaddr(unsigned long pa, unsigned long va); -static void shmedia_unmapioaddr(unsigned long vaddr); -static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz); - -/* - * We have the same problem as the SPARC, so lets have the same comment: - * Our mini-allocator... - * Boy this is gross! We need it because we must map I/O for - * timers and interrupt controller before the kmalloc is available. - */ - -#define XNMLN 15 -#define XNRES 10 - -struct xresource { - struct resource xres; /* Must be first */ - int xflag; /* 1 == used */ - char xname[XNMLN+1]; -}; - -static struct xresource xresv[XNRES]; - -static struct xresource *xres_alloc(void) -{ - struct xresource *xrp; - int n; - - xrp = xresv; - for (n = 0; n < XNRES; n++) { - if (xrp->xflag == 0) { - xrp->xflag = 1; - return xrp; - } - xrp++; - } - return NULL; -} - -static void xres_free(struct xresource *xrp) -{ - xrp->xflag = 0; -} - -static struct resource *shmedia_find_resource(struct resource *root, - unsigned long vaddr) -{ - struct resource *res; - - for (res = root->child; res; res = res->sibling) - if (res->start <= vaddr && res->end >= vaddr) - return res; - - return NULL; -} - -static unsigned long shmedia_alloc_io(unsigned long phys, unsigned long size, - const char *name) -{ - static int printed_full = 0; - struct xresource *xres; - struct resource *res; - char *tack; - int tlen; - - if (name == NULL) name = "???"; - - if ((xres = xres_alloc()) != 0) { - tack = xres->xname; - res = &xres->xres; - } else { - if (!printed_full) { - printk("%s: done with statics, switching to kmalloc\n", - __FUNCTION__); - printed_full = 1; - } - tlen = strlen(name); - tack = kmalloc(sizeof (struct resource) + tlen + 1, GFP_KERNEL); - if (!tack) - return -ENOMEM; - memset(tack, 0, sizeof(struct resource)); - res = (struct resource *) tack; - tack += sizeof (struct resource); - } - - strncpy(tack, name, XNMLN); - tack[XNMLN] = 0; - res->name = tack; - - return shmedia_ioremap(res, phys, size); -} - -static unsigned long shmedia_ioremap(struct resource *res, u32 pa, int sz) -{ - unsigned long offset = ((unsigned long) pa) & (~PAGE_MASK); - unsigned long round_sz = (offset + sz + PAGE_SIZE-1) & PAGE_MASK; - unsigned long va; - unsigned int psz; - - if (allocate_resource(&shmedia_iomap, res, round_sz, - shmedia_iomap.start, shmedia_iomap.end, - PAGE_SIZE, NULL, NULL) != 0) { - panic("alloc_io_res(%s): cannot occupy\n", - (res->name != NULL)? res->name: "???"); - } - - va = res->start; - pa &= PAGE_MASK; - - psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE; - - /* log at boot time ... */ - printk("mapioaddr: %6s [%2d page%s] va 0x%08lx pa 0x%08x\n", - ((res->name != NULL) ? res->name : "???"), - psz, psz == 1 ? " " : "s", va, pa); - - for (psz = res->end - res->start + 1; psz != 0; psz -= PAGE_SIZE) { - shmedia_mapioaddr(pa, va); - va += PAGE_SIZE; - pa += PAGE_SIZE; - } - - res->start += offset; - res->end = res->start + sz - 1; /* not strictly necessary.. */ - - return res->start; -} - -static void shmedia_free_io(struct resource *res) -{ - unsigned long len = res->end - res->start + 1; - - BUG_ON((len & (PAGE_SIZE - 1)) != 0); - - while (len) { - len -= PAGE_SIZE; - shmedia_unmapioaddr(res->start + len); - } - - release_resource(res); -} - -static __init_refok void *sh64_get_page(void) -{ - extern int after_bootmem; - void *page; - - if (after_bootmem) { - page = (void *)get_zeroed_page(GFP_ATOMIC); - } else { - page = alloc_bootmem_pages(PAGE_SIZE); - } - - if (!page || ((unsigned long)page & ~PAGE_MASK)) - panic("sh64_get_page: Out of memory already?\n"); - - return page; -} - -static void shmedia_mapioaddr(unsigned long pa, unsigned long va) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep, pte; - pgprot_t prot; - unsigned long flags = 1; /* 1 = CB0-1 device */ - - pr_debug("shmedia_mapiopage pa %08lx va %08lx\n", pa, va); - - pgdp = pgd_offset_k(va); - if (pgd_none(*pgdp) || !pgd_present(*pgdp)) { - pmdp = (pmd_t *)sh64_get_page(); - set_pgd(pgdp, __pgd((unsigned long)pmdp | _KERNPG_TABLE)); - } - - pmdp = pmd_offset(pgdp, va); - if (pmd_none(*pmdp) || !pmd_present(*pmdp) ) { - ptep = (pte_t *)sh64_get_page(); - set_pmd(pmdp, __pmd((unsigned long)ptep + _PAGE_TABLE)); - } - - prot = __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | - _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_SHARED | flags); - - pte = pfn_pte(pa >> PAGE_SHIFT, prot); - ptep = pte_offset_kernel(pmdp, va); - - if (!pte_none(*ptep) && - pte_val(*ptep) != pte_val(pte)) - pte_ERROR(*ptep); - - set_pte(ptep, pte); - - flush_tlb_kernel_range(va, PAGE_SIZE); -} - -static void shmedia_unmapioaddr(unsigned long vaddr) -{ - pgd_t *pgdp; - pmd_t *pmdp; - pte_t *ptep; - - pgdp = pgd_offset_k(vaddr); - pmdp = pmd_offset(pgdp, vaddr); - - if (pmd_none(*pmdp) || pmd_bad(*pmdp)) - return; - - ptep = pte_offset_kernel(pmdp, vaddr); - - if (pte_none(*ptep) || !pte_present(*ptep)) - return; - - clear_page((void *)ptep); - pte_clear(&init_mm, vaddr, ptep); -} - -unsigned long onchip_remap(unsigned long phys, unsigned long size, const char *name) -{ - if (size < PAGE_SIZE) - size = PAGE_SIZE; - - return shmedia_alloc_io(phys, size, name); -} - -void onchip_unmap(unsigned long vaddr) -{ - struct resource *res; - unsigned int psz; - - res = shmedia_find_resource(&shmedia_iomap, vaddr); - if (!res) { - printk(KERN_ERR "%s: Failed to free 0x%08lx\n", - __FUNCTION__, vaddr); - return; - } - - psz = (res->end - res->start + (PAGE_SIZE - 1)) / PAGE_SIZE; - - printk(KERN_DEBUG "unmapioaddr: %6s [%2d page%s] freed\n", - res->name, psz, psz == 1 ? " " : "s"); - - shmedia_free_io(res); - - if ((char *)res >= (char *)xresv && - (char *)res < (char *)&xresv[XNRES]) { - xres_free((struct xresource *)res); - } else { - kfree(res); - } -} - -#ifdef CONFIG_PROC_FS -static int -ioremap_proc_info(char *buf, char **start, off_t fpos, int length, int *eof, - void *data) -{ - char *p = buf, *e = buf + length; - struct resource *r; - const char *nm; - - for (r = ((struct resource *)data)->child; r != NULL; r = r->sibling) { - if (p + 32 >= e) /* Better than nothing */ - break; - if ((nm = r->name) == 0) nm = "???"; - p += sprintf(p, "%08lx-%08lx: %s\n", - (unsigned long)r->start, - (unsigned long)r->end, nm); - } - - return p-buf; -} -#endif /* CONFIG_PROC_FS */ - -static int __init register_proc_onchip(void) -{ -#ifdef CONFIG_PROC_FS - create_proc_read_entry("io_map",0,0, ioremap_proc_info, &shmedia_iomap); -#endif - return 0; -} - -__initcall(register_proc_onchip); diff -puN arch/sh64/mm/tlb.c~git-sh /dev/null --- a/arch/sh64/mm/tlb.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * arch/sh64/mm/tlb.c - * - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2003 Richard Curnow - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ -#include -#include -#include -#include -#include - -/** - * sh64_tlb_init - * - * Perform initial setup for the DTLB and ITLB. - */ -int __init sh64_tlb_init(void) -{ - /* Assign some sane DTLB defaults */ - cpu_data->dtlb.entries = 64; - cpu_data->dtlb.step = 0x10; - - cpu_data->dtlb.first = DTLB_FIXED | cpu_data->dtlb.step; - cpu_data->dtlb.next = cpu_data->dtlb.first; - - cpu_data->dtlb.last = DTLB_FIXED | - ((cpu_data->dtlb.entries - 1) * - cpu_data->dtlb.step); - - /* And again for the ITLB */ - cpu_data->itlb.entries = 64; - cpu_data->itlb.step = 0x10; - - cpu_data->itlb.first = ITLB_FIXED | cpu_data->itlb.step; - cpu_data->itlb.next = cpu_data->itlb.first; - cpu_data->itlb.last = ITLB_FIXED | - ((cpu_data->itlb.entries - 1) * - cpu_data->itlb.step); - - return 0; -} - -/** - * sh64_next_free_dtlb_entry - * - * Find the next available DTLB entry - */ -unsigned long long sh64_next_free_dtlb_entry(void) -{ - return cpu_data->dtlb.next; -} - -/** - * sh64_get_wired_dtlb_entry - * - * Allocate a wired (locked-in) entry in the DTLB - */ -unsigned long long sh64_get_wired_dtlb_entry(void) -{ - unsigned long long entry = sh64_next_free_dtlb_entry(); - - cpu_data->dtlb.first += cpu_data->dtlb.step; - cpu_data->dtlb.next += cpu_data->dtlb.step; - - return entry; -} - -/** - * sh64_put_wired_dtlb_entry - * - * @entry: Address of TLB slot. - * - * Free a wired (locked-in) entry in the DTLB. - * - * Works like a stack, last one to allocate must be first one to free. - */ -int sh64_put_wired_dtlb_entry(unsigned long long entry) -{ - __flush_tlb_slot(entry); - - /* - * We don't do any particularly useful tracking of wired entries, - * so this approach works like a stack .. last one to be allocated - * has to be the first one to be freed. - * - * We could potentially load wired entries into a list and work on - * rebalancing the list periodically (which also entails moving the - * contents of a TLB entry) .. though I have a feeling that this is - * more trouble than it's worth. - */ - - /* - * Entry must be valid .. we don't want any ITLB addresses! - */ - if (entry <= DTLB_FIXED) - return -EINVAL; - - /* - * Next, check if we're within range to be freed. (ie, must be the - * entry beneath the first 'free' entry! - */ - if (entry < (cpu_data->dtlb.first - cpu_data->dtlb.step)) - return -EINVAL; - - /* If we are, then bring this entry back into the list */ - cpu_data->dtlb.first -= cpu_data->dtlb.step; - cpu_data->dtlb.next = entry; - - return 0; -} - -/** - * sh64_setup_tlb_slot - * - * @config_addr: Address of TLB slot. - * @eaddr: Virtual address. - * @asid: Address Space Identifier. - * @paddr: Physical address. - * - * Load up a virtual<->physical translation for @eaddr<->@paddr in the - * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry). - */ -inline void sh64_setup_tlb_slot(unsigned long long config_addr, - unsigned long eaddr, - unsigned long asid, - unsigned long paddr) -{ - unsigned long long pteh, ptel; - - /* Sign extension */ -#if (NEFF == 32) - pteh = (unsigned long long)(signed long long)(signed long) eaddr; -#else -#error "Can't sign extend more than 32 bits yet" -#endif - pteh &= PAGE_MASK; - pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID; -#if (NEFF == 32) - ptel = (unsigned long long)(signed long long)(signed long) paddr; -#else -#error "Can't sign extend more than 32 bits yet" -#endif - ptel &= PAGE_MASK; - ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE); - - asm volatile("putcfg %0, 1, %1\n\t" - "putcfg %0, 0, %2\n" - : : "r" (config_addr), "r" (ptel), "r" (pteh)); -} - -/** - * sh64_teardown_tlb_slot - * - * @config_addr: Address of TLB slot. - * - * Teardown any existing mapping in the TLB slot @config_addr. - */ -inline void sh64_teardown_tlb_slot(unsigned long long config_addr) - __attribute__ ((alias("__flush_tlb_slot"))); - diff -puN arch/sh64/mm/tlbmiss.c~git-sh /dev/null --- a/arch/sh64/mm/tlbmiss.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * arch/sh64/mm/tlbmiss.c - * - * Original code from fault.c - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * Fast PTE->TLB refill path - * Copyright (C) 2003 Richard.Curnow@superh.com - * - * IMPORTANT NOTES : - * The do_fast_page_fault function is called from a context in entry.S where very few registers - * have been saved. In particular, the code in this file must be compiled not to use ANY - * caller-save registers that are not part of the restricted save set. Also, it means that - * code in this file must not make calls to functions elsewhere in the kernel, or else the - * excepting context will see corruption in its caller-save registers. Plus, the entry.S save - * area is non-reentrant, so this code has to run with SR.BL==1, i.e. no interrupts taken inside - * it and panic on any exception. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include /* required by inline asm statements */ - -/* Callable from fault.c, so not static */ -inline void __do_tlb_refill(unsigned long address, - unsigned long long is_text_not_data, pte_t *pte) -{ - unsigned long long ptel; - unsigned long long pteh=0; - struct tlb_info *tlbp; - unsigned long long next; - - /* Get PTEL first */ - ptel = pte_val(*pte); - - /* - * Set PTEH register - */ - pteh = address & MMU_VPN_MASK; - - /* Sign extend based on neff. */ -#if (NEFF == 32) - /* Faster sign extension */ - pteh = (unsigned long long)(signed long long)(signed long)pteh; -#else - /* General case */ - pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh; -#endif - - /* Set the ASID. */ - pteh |= get_asid() << PTEH_ASID_SHIFT; - pteh |= PTEH_VALID; - - /* Set PTEL register, set_pte has performed the sign extension */ - ptel &= _PAGE_FLAGS_HARDWARE_MASK; /* drop software flags */ - - tlbp = is_text_not_data ? &(cpu_data->itlb) : &(cpu_data->dtlb); - next = tlbp->next; - __flush_tlb_slot(next); - asm volatile ("putcfg %0,1,%2\n\n\t" - "putcfg %0,0,%1\n" - : : "r" (next), "r" (pteh), "r" (ptel) ); - - next += TLB_STEP; - if (next > tlbp->last) next = tlbp->first; - tlbp->next = next; - -} - -static int handle_vmalloc_fault(struct mm_struct *mm, unsigned long protection_flags, - unsigned long long textaccess, - unsigned long address) -{ - pgd_t *dir; - pmd_t *pmd; - static pte_t *pte; - pte_t entry; - - dir = pgd_offset_k(address); - pmd = pmd_offset(dir, address); - - if (pmd_none(*pmd)) { - return 0; - } - - if (pmd_bad(*pmd)) { - pmd_clear(pmd); - return 0; - } - - pte = pte_offset_kernel(pmd, address); - entry = *pte; - - if (pte_none(entry) || !pte_present(entry)) { - return 0; - } - - if ((pte_val(entry) & protection_flags) != protection_flags) { - return 0; - } - - __do_tlb_refill(address, textaccess, pte); - - return 1; -} - -static int handle_tlbmiss(struct mm_struct *mm, unsigned long long protection_flags, - unsigned long long textaccess, - unsigned long address) -{ - pgd_t *dir; - pmd_t *pmd; - pte_t *pte; - pte_t entry; - - /* NB. The PGD currently only contains a single entry - there is no - page table tree stored for the top half of the address space since - virtual pages in that region should never be mapped in user mode. - (In kernel mode, the only things in that region are the 512Mb super - page (locked in), and vmalloc (modules) + I/O device pages (handled - by handle_vmalloc_fault), so no PGD for the upper half is required - by kernel mode either). - - See how mm->pgd is allocated and initialised in pgd_alloc to see why - the next test is necessary. - RPC */ - if (address >= (unsigned long) TASK_SIZE) { - /* upper half - never has page table entries. */ - return 0; - } - dir = pgd_offset(mm, address); - if (pgd_none(*dir)) { - return 0; - } - if (!pgd_present(*dir)) { - return 0; - } - - pmd = pmd_offset(dir, address); - if (pmd_none(*pmd)) { - return 0; - } - if (!pmd_present(*pmd)) { - return 0; - } - pte = pte_offset_kernel(pmd, address); - entry = *pte; - if (pte_none(entry)) { - return 0; - } - if (!pte_present(entry)) { - return 0; - } - - /* If the page doesn't have sufficient protection bits set to service the - kind of fault being handled, there's not much point doing the TLB refill. - Punt the fault to the general handler. */ - if ((pte_val(entry) & protection_flags) != protection_flags) { - return 0; - } - - __do_tlb_refill(address, textaccess, pte); - - return 1; -} - -/* Put all this information into one structure so that everything is just arithmetic - relative to a single base address. This reduces the number of movi/shori pairs needed - just to load addresses of static data. */ -struct expevt_lookup { - unsigned short protection_flags[8]; - unsigned char is_text_access[8]; - unsigned char is_write_access[8]; -}; - -#define PRU (1<<9) -#define PRW (1<<8) -#define PRX (1<<7) -#define PRR (1<<6) - -#define DIRTY (_PAGE_DIRTY | _PAGE_ACCESSED) -#define YOUNG (_PAGE_ACCESSED) - -/* Sized as 8 rather than 4 to allow checking the PTE's PRU bit against whether - the fault happened in user mode or privileged mode. */ -static struct expevt_lookup expevt_lookup_table = { - .protection_flags = {PRX, PRX, 0, 0, PRR, PRR, PRW, PRW}, - .is_text_access = {1, 1, 0, 0, 0, 0, 0, 0} -}; - -/* - This routine handles page faults that can be serviced just by refilling a - TLB entry from an existing page table entry. (This case represents a very - large majority of page faults.) Return 1 if the fault was successfully - handled. Return 0 if the fault could not be handled. (This leads into the - general fault handling in fault.c which deals with mapping file-backed - pages, stack growth, segmentation faults, swapping etc etc) - */ -asmlinkage int do_fast_page_fault(unsigned long long ssr_md, unsigned long long expevt, - unsigned long address) -{ - struct task_struct *tsk; - struct mm_struct *mm; - unsigned long long textaccess; - unsigned long long protection_flags; - unsigned long long index; - unsigned long long expevt4; - - /* The next few lines implement a way of hashing EXPEVT into a small array index - which can be used to lookup parameters specific to the type of TLBMISS being - handled. Note: - ITLBMISS has EXPEVT==0xa40 - RTLBMISS has EXPEVT==0x040 - WTLBMISS has EXPEVT==0x060 - */ - - expevt4 = (expevt >> 4); - /* TODO : xor ssr_md into this expression too. Then we can check that PRU is set - when it needs to be. */ - index = expevt4 ^ (expevt4 >> 5); - index &= 7; - protection_flags = expevt_lookup_table.protection_flags[index]; - textaccess = expevt_lookup_table.is_text_access[index]; - -#ifdef CONFIG_SH64_PROC_TLB - ++calls_to_do_fast_page_fault; -#endif - - /* SIM - * Note this is now called with interrupts still disabled - * This is to cope with being called for a missing IO port - * address with interrupts disabled. This should be fixed as - * soon as we have a better 'fast path' miss handler. - * - * Plus take care how you try and debug this stuff. - * For example, writing debug data to a port which you - * have just faulted on is not going to work. - */ - - tsk = current; - mm = tsk->mm; - - if ((address >= VMALLOC_START && address < VMALLOC_END) || - (address >= IOBASE_VADDR && address < IOBASE_END)) { - if (ssr_md) { - /* Process-contexts can never have this address range mapped */ - if (handle_vmalloc_fault(mm, protection_flags, textaccess, address)) { - return 1; - } - } - } else if (!in_interrupt() && mm) { - if (handle_tlbmiss(mm, protection_flags, textaccess, address)) { - return 1; - } - } - - return 0; -} - diff -puN arch/sh64/oprofile/Makefile~git-sh /dev/null --- a/arch/sh64/oprofile/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -obj-$(CONFIG_OPROFILE) += oprofile.o - -DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \ - oprof.o cpu_buffer.o buffer_sync.o \ - event_buffer.o oprofile_files.o \ - oprofilefs.o oprofile_stats.o \ - timer_int.o ) - -profdrvr-y := op_model_null.o - -oprofile-y := $(DRIVER_OBJS) $(profdrvr-y) - diff -puN arch/sh64/oprofile/op_model_null.c~git-sh /dev/null --- a/arch/sh64/oprofile/op_model_null.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * arch/sh64/oprofile/op_model_null.c - * - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include -#include - -int __init oprofile_arch_init(struct oprofile_operations *ops) -{ - return -ENODEV; -} - -void oprofile_arch_exit(void) -{ -} - diff -puN drivers/rtc/Kconfig~git-sh drivers/rtc/Kconfig --- a/drivers/rtc/Kconfig~git-sh +++ a/drivers/rtc/Kconfig @@ -404,7 +404,7 @@ config RTC_DRV_SA1100 config RTC_DRV_SH tristate "SuperH On-Chip RTC" - depends on RTC_CLASS && (CPU_SH3 || CPU_SH4) + depends on RTC_CLASS && SUPERH help Say Y here to enable support for the on-chip RTC found in most SuperH processors. diff -puN drivers/rtc/rtc-sh.c~git-sh drivers/rtc/rtc-sh.c --- a/drivers/rtc/rtc-sh.c~git-sh +++ a/drivers/rtc/rtc-sh.c @@ -26,17 +26,7 @@ #include #define DRV_NAME "sh-rtc" -#define DRV_VERSION "0.1.3" - -#ifdef CONFIG_CPU_SH3 -#define rtc_reg_size sizeof(u16) -#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ -#define RTC_DEF_CAPABILITIES 0UL -#elif defined(CONFIG_CPU_SH4) -#define rtc_reg_size sizeof(u32) -#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ -#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR -#endif +#define DRV_VERSION "0.1.6" #define RTC_REG(r) ((r) * rtc_reg_size) @@ -58,6 +48,18 @@ #define RCR1 RTC_REG(14) /* Control */ #define RCR2 RTC_REG(15) /* Control */ +/* + * Note on RYRAR and RCR3: Up until this point most of the register + * definitions are consistent across all of the available parts. However, + * the placement of the optional RYRAR and RCR3 (the RYRAR control + * register used to control RYRCNT/RYRAR compare) varies considerably + * across various parts, occasionally being mapped in to a completely + * unrelated address space. For proper RYRAR support a separate resource + * would have to be handed off, but as this is purely optional in + * practice, we simply opt not to support it, thereby keeping the code + * quite a bit more simplified. + */ + /* ALARM Bits - or with BCD encoded value */ #define AR_ENB 0x80 /* Enable for alarm cmp */ diff -puN drivers/serial/sh-sci.h~git-sh drivers/serial/sh-sci.h --- a/drivers/serial/sh-sci.h~git-sh +++ a/drivers/serial/sh-sci.h @@ -142,7 +142,9 @@ # define SCIF_OPER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY -#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \ + defined(CONFIG_CPU_SUBTYPE_SH7206) || \ + defined(CONFIG_CPU_SUBTYPE_SH7263) # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ # define SCSPTR1 0xfffe8820 /* 16 bit SCIF */ # define SCSPTR2 0xfffe9020 /* 16 bit SCIF */ @@ -617,7 +619,9 @@ static inline int sci_rxd_in(struct uart return ctrl_inw(SCSPTR5) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7206) +#elif defined(CONFIG_CPU_SUBTYPE_SH7203) || \ + defined(CONFIG_CPU_SUBTYPE_SH7206) || \ + defined(CONFIG_CPU_SUBTYPE_SH7263) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xfffe8000) diff -puN include/asm-sh/addrspace.h~git-sh include/asm-sh/addrspace.h --- a/include/asm-sh/addrspace.h~git-sh +++ a/include/asm-sh/addrspace.h @@ -9,24 +9,21 @@ */ #ifndef __ASM_SH_ADDRSPACE_H #define __ASM_SH_ADDRSPACE_H + #ifdef __KERNEL__ #include -/* Memory segments (32bit Privileged mode addresses) */ -#ifndef CONFIG_CPU_SH2A -#define P0SEG 0x00000000 -#define P1SEG 0x80000000 -#define P2SEG 0xa0000000 -#define P3SEG 0xc0000000 -#define P4SEG 0xe0000000 -#else -#define P0SEG 0x00000000 -#define P1SEG 0x00000000 -#define P2SEG 0x20000000 -#define P3SEG 0x00000000 -#define P4SEG 0x80000000 -#endif +/* If this CPU supports segmentation, hook up the helpers */ +#ifdef P1SEG + +/* + [ P0/U0 (virtual) ] 0x00000000 <------ User space + [ P1 (fixed) cached ] 0x80000000 <------ Kernel space + [ P2 (fixed) non-cachable] 0xA0000000 <------ Physical access + [ P3 (virtual) cached] 0xC0000000 <------ vmalloced area + [ P4 control ] 0xE0000000 + */ /* Returns the privileged segment base of a given address */ #define PXSEG(a) (((unsigned long)(a)) & 0xe0000000) @@ -34,13 +31,23 @@ /* Returns the physical address of a PnSEG (n=1,2) address */ #define PHYSADDR(a) (((unsigned long)(a)) & 0x1fffffff) +#ifdef CONFIG_29BIT /* * Map an address to a certain privileged segment */ -#define P1SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P1SEG)) -#define P2SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P2SEG)) -#define P3SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG)) -#define P4SEGADDR(a) ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG)) +#define P1SEGADDR(a) \ + ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P1SEG)) +#define P2SEGADDR(a) \ + ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P2SEG)) +#define P3SEGADDR(a) \ + ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P3SEG)) +#define P4SEGADDR(a) \ + ((__typeof__(a))(((unsigned long)(a) & 0x1fffffff) | P4SEG)) +#endif /* 29BIT */ +#endif /* P1SEG */ + +/* Check if an address can be reached in 29 bits */ +#define IS_29BIT(a) (((unsigned long)(a)) < 0x20000000) #endif /* __KERNEL__ */ #endif /* __ASM_SH_ADDRSPACE_H */ diff -puN /dev/null include/asm-sh/atomic-grb.h --- /dev/null +++ a/include/asm-sh/atomic-grb.h @@ -0,0 +1,169 @@ +#ifndef __ASM_SH_ATOMIC_GRB_H +#define __ASM_SH_ATOMIC_GRB_H + +static inline void atomic_add(int i, atomic_t *v) +{ + int tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " add %2, %0 \n\t" /* add */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (i) + : "memory" , "r0", "r1"); +} + +static inline void atomic_sub(int i, atomic_t *v) +{ + int tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " sub %2, %0 \n\t" /* sub */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (i) + : "memory" , "r0", "r1"); +} + +static inline int atomic_add_return(int i, atomic_t *v) +{ + int tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " add %2, %0 \n\t" /* add */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (i) + : "memory" , "r0", "r1"); + + return tmp; +} + +static inline int atomic_sub_return(int i, atomic_t *v) +{ + int tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " sub %2, %0 \n\t" /* sub */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (i) + : "memory", "r0", "r1"); + + return tmp; +} + +static inline void atomic_clear_mask(unsigned int mask, atomic_t *v) +{ + int tmp; + unsigned int _mask = ~mask; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " and %2, %0 \n\t" /* add */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (_mask) + : "memory" , "r0", "r1"); +} + +static inline void atomic_set_mask(unsigned int mask, atomic_t *v) +{ + int tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " or %2, %0 \n\t" /* or */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (v) + : "r" (mask) + : "memory" , "r0", "r1"); +} + +static inline int atomic_cmpxchg(atomic_t *v, int old, int new) +{ + int ret; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" + " nop \n\t" + " mov r15, r1 \n\t" + " mov #-8, r15 \n\t" + " mov.l @%1, %0 \n\t" + " cmp/eq %2, %0 \n\t" + " bf 1f \n\t" + " mov.l %3, @%1 \n\t" + "1: mov r1, r15 \n\t" + : "=&r" (ret) + : "r" (v), "r" (old), "r" (new) + : "memory" , "r0", "r1" , "t"); + + return ret; +} + +static inline int atomic_add_unless(atomic_t *v, int a, int u) +{ + int ret; + unsigned long tmp; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" + " nop \n\t" + " mov r15, r1 \n\t" + " mov #-12, r15 \n\t" + " mov.l @%2, %1 \n\t" + " mov %1, %0 \n\t" + " cmp/eq %4, %0 \n\t" + " bt/s 1f \n\t" + " add %3, %1 \n\t" + " mov.l %1, @%2 \n\t" + "1: mov r1, r15 \n\t" + : "=&r" (ret), "=&r" (tmp) + : "r" (v), "r" (a), "r" (u) + : "memory" , "r0", "r1" , "t"); + + return ret != u; +} +#endif /* __ASM_SH_ATOMIC_GRB_H */ diff -puN include/asm-sh/atomic.h~git-sh include/asm-sh/atomic.h --- a/include/asm-sh/atomic.h~git-sh +++ a/include/asm-sh/atomic.h @@ -17,7 +17,9 @@ typedef struct { volatile int counter; } #include #include -#ifdef CONFIG_CPU_SH4A +#if defined(CONFIG_GUSA_RB) +#include +#elif defined(CONFIG_CPU_SH4A) #include #else #include @@ -44,6 +46,7 @@ typedef struct { volatile int counter; } #define atomic_inc(v) atomic_add(1,(v)) #define atomic_dec(v) atomic_sub(1,(v)) +#ifndef CONFIG_GUSA_RB static inline int atomic_cmpxchg(atomic_t *v, int old, int new) { int ret; @@ -58,8 +61,6 @@ static inline int atomic_cmpxchg(atomic_ return ret; } -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - static inline int atomic_add_unless(atomic_t *v, int a, int u) { int ret; @@ -73,6 +74,9 @@ static inline int atomic_add_unless(atom return ret != u; } +#endif + +#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) /* Atomic operations are already serializing on SH */ diff -puN include/asm-sh/auxvec.h~git-sh include/asm-sh/auxvec.h --- a/include/asm-sh/auxvec.h~git-sh +++ a/include/asm-sh/auxvec.h @@ -6,6 +6,12 @@ * for more of them. */ +/* + * This entry gives some information about the FPU initialization + * performed by the kernel. + */ +#define AT_FPUCW 18 /* Used FPU control word. */ + #ifdef CONFIG_VSYSCALL /* * Only define this in the vsyscall case, the entry point to @@ -15,4 +21,16 @@ #define AT_SYSINFO_EHDR 33 #endif +/* + * More complete cache descriptions than AT_[DIU]CACHEBSIZE. If the + * value is -1, then the cache doesn't exist. Otherwise: + * + * bit 0-3: Cache set-associativity; 0 means fully associative. + * bit 4-7: Log2 of cacheline size. + * bit 8-31: Size of the entire cache >> 8. + */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 + #endif /* __ASM_SH_AUXVEC_H */ diff -puN /dev/null include/asm-sh/bitops-grb.h --- /dev/null +++ a/include/asm-sh/bitops-grb.h @@ -0,0 +1,169 @@ +#ifndef __ASM_SH_BITOPS_GRB_H +#define __ASM_SH_BITOPS_GRB_H + +static inline void set_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " or %2, %0 \n\t" /* or */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (a) + : "r" (mask) + : "memory" , "r0", "r1"); +} + +static inline void clear_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = ~(1 << (nr & 0x1f)); + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " and %2, %0 \n\t" /* and */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (a) + : "r" (mask) + : "memory" , "r0", "r1"); +} + +static inline void change_bit(int nr, volatile void * addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%1, %0 \n\t" /* load old value */ + " xor %2, %0 \n\t" /* xor */ + " mov.l %0, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "+r" (a) + : "r" (mask) + : "memory" , "r0", "r1"); +} + +static inline int test_and_set_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-14, r15 \n\t" /* LOGIN: r15 = size */ + " mov.l @%2, %0 \n\t" /* load old value */ + " mov %0, %1 \n\t" + " tst %1, %3 \n\t" /* T = ((*a & mask) == 0) */ + " mov #-1, %1 \n\t" /* retvat = -1 */ + " negc %1, %1 \n\t" /* retval = (mask & *a) != 0 */ + " or %3, %0 \n\t" + " mov.l %0, @%2 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "=&r" (retval), + "+r" (a) + : "r" (mask) + : "memory" , "r0", "r1" ,"t"); + + return retval; +} + +static inline int test_and_clear_bit(int nr, volatile void * addr) +{ + int mask, retval,not_mask; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + + not_mask = ~mask; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-14, r15 \n\t" /* LOGIN */ + " mov.l @%2, %0 \n\t" /* load old value */ + " mov %0, %1 \n\t" /* %1 = *a */ + " tst %1, %3 \n\t" /* T = ((*a & mask) == 0) */ + " mov #-1, %1 \n\t" /* retvat = -1 */ + " negc %1, %1 \n\t" /* retval = (mask & *a) != 0 */ + " and %4, %0 \n\t" + " mov.l %0, @%2 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "=&r" (retval), + "+r" (a) + : "r" (mask), + "r" (not_mask) + : "memory" , "r0", "r1", "t"); + + return retval; +} + +static inline int test_and_change_bit(int nr, volatile void * addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + unsigned long tmp; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-14, r15 \n\t" /* LOGIN */ + " mov.l @%2, %0 \n\t" /* load old value */ + " mov %0, %1 \n\t" /* %1 = *a */ + " tst %1, %3 \n\t" /* T = ((*a & mask) == 0) */ + " mov #-1, %1 \n\t" /* retvat = -1 */ + " negc %1, %1 \n\t" /* retval = (mask & *a) != 0 */ + " xor %3, %0 \n\t" + " mov.l %0, @%2 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (tmp), + "=&r" (retval), + "+r" (a) + : "r" (mask) + : "memory" , "r0", "r1", "t"); + + return retval; +} +#endif /* __ASM_SH_BITOPS_GRB_H */ diff -puN /dev/null include/asm-sh/bitops-irq.h --- /dev/null +++ a/include/asm-sh/bitops-irq.h @@ -0,0 +1,91 @@ +#ifndef __ASM_SH_BITOPS_IRQ_H +#define __ASM_SH_BITOPS_IRQ_H + +static inline void set_bit(int nr, volatile void *addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + *a |= mask; + local_irq_restore(flags); +} + +static inline void clear_bit(int nr, volatile void *addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + *a &= ~mask; + local_irq_restore(flags); +} + +static inline void change_bit(int nr, volatile void *addr) +{ + int mask; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + *a ^= mask; + local_irq_restore(flags); +} + +static inline int test_and_set_bit(int nr, volatile void *addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + retval = (mask & *a) != 0; + *a |= mask; + local_irq_restore(flags); + + return retval; +} + +static inline int test_and_clear_bit(int nr, volatile void *addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + retval = (mask & *a) != 0; + *a &= ~mask; + local_irq_restore(flags); + + return retval; +} + +static inline int test_and_change_bit(int nr, volatile void *addr) +{ + int mask, retval; + volatile unsigned int *a = addr; + unsigned long flags; + + a += nr >> 5; + mask = 1 << (nr & 0x1f); + local_irq_save(flags); + retval = (mask & *a) != 0; + *a ^= mask; + local_irq_restore(flags); + + return retval; +} + +#endif /* __ASM_SH_BITOPS_IRQ_H */ diff -puN include/asm-sh/bitops.h~git-sh include/asm-sh/bitops.h --- a/include/asm-sh/bitops.h~git-sh +++ a/include/asm-sh/bitops.h @@ -11,100 +11,22 @@ /* For __swab32 */ #include -static inline void set_bit(int nr, volatile void * addr) -{ - int mask; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a |= mask; - local_irq_restore(flags); -} +#ifdef CONFIG_GUSA_RB +#include +#else +#include +#endif + /* * clear_bit() doesn't provide any barrier for the compiler. */ #define smp_mb__before_clear_bit() barrier() #define smp_mb__after_clear_bit() barrier() -static inline void clear_bit(int nr, volatile void * addr) -{ - int mask; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a &= ~mask; - local_irq_restore(flags); -} - -static inline void change_bit(int nr, volatile void * addr) -{ - int mask; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a ^= mask; - local_irq_restore(flags); -} - -static inline int test_and_set_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a |= mask; - local_irq_restore(flags); - - return retval; -} - -static inline int test_and_clear_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a &= ~mask; - local_irq_restore(flags); - - return retval; -} - -static inline int test_and_change_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a ^= mask; - local_irq_restore(flags); - - return retval; -} #include +#ifdef CONFIG_SUPERH32 static inline unsigned long ffz(unsigned long word) { unsigned long result; @@ -138,6 +60,31 @@ static inline unsigned long __ffs(unsign : "t"); return result; } +#else +static inline unsigned long ffz(unsigned long word) +{ + unsigned long result, __d2, __d3; + + __asm__("gettr tr0, %2\n\t" + "pta $+32, tr0\n\t" + "andi %1, 1, %3\n\t" + "beq %3, r63, tr0\n\t" + "pta $+4, tr0\n" + "0:\n\t" + "shlri.l %1, 1, %1\n\t" + "addi %0, 1, %0\n\t" + "andi %1, 1, %3\n\t" + "beqi %3, 1, tr0\n" + "1:\n\t" + "ptabs %2, tr0\n\t" + : "=r" (result), "=r" (word), "=r" (__d2), "=r" (__d3) + : "0" (0L), "1" (word)); + + return result; +} + +#include +#endif #include #include diff -puN include/asm-sh/bug.h~git-sh include/asm-sh/bug.h --- a/include/asm-sh/bug.h~git-sh +++ a/include/asm-sh/bug.h @@ -3,7 +3,7 @@ #define TRAPA_BUG_OPCODE 0xc33e /* trapa #0x3e */ -#ifdef CONFIG_BUG +#ifdef CONFIG_GENERIC_BUG #define HAVE_ARCH_BUG #define HAVE_ARCH_WARN_ON @@ -72,12 +72,7 @@ do { \ unlikely(__ret_warn_on); \ }) -struct pt_regs; - -/* arch/sh/kernel/traps.c */ -void handle_BUG(struct pt_regs *); - -#endif /* CONFIG_BUG */ +#endif /* CONFIG_GENERIC_BUG */ #include diff -puN include/asm-sh/bugs.h~git-sh include/asm-sh/bugs.h --- a/include/asm-sh/bugs.h~git-sh +++ a/include/asm-sh/bugs.h @@ -25,7 +25,7 @@ static void __init check_bugs(void) case CPU_SH7619: *p++ = '2'; break; - case CPU_SH7206: + case CPU_SH7203 ... CPU_SH7263: *p++ = '2'; *p++ = 'a'; break; @@ -48,9 +48,16 @@ static void __init check_bugs(void) *p++ = 's'; *p++ = 'p'; break; - default: - *p++ = '?'; - *p++ = '!'; + case CPU_SH5_101 ... CPU_SH5_103: + *p++ = '6'; + *p++ = '4'; + break; + case CPU_SH_NONE: + /* + * Specifically use CPU_SH_NONE rather than default:, + * so we're able to have the compiler whine about + * unhandled enumerations. + */ break; } diff -puN include/asm-sh/byteorder.h~git-sh include/asm-sh/byteorder.h --- a/include/asm-sh/byteorder.h~git-sh +++ a/include/asm-sh/byteorder.h @@ -3,40 +3,55 @@ /* * Copyright (C) 1999 Niibe Yutaka + * Copyright (C) 2000, 2001 Paolo Alberelli */ - -#include #include +#include -static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x) +static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) { - __asm__("swap.b %0, %0\n\t" - "swap.w %0, %0\n\t" - "swap.b %0, %0" + __asm__( +#ifdef CONFIG_SUPERH32 + "swap.b %0, %0\n\t" + "swap.w %0, %0\n\t" + "swap.b %0, %0" +#else + "byterev %0, %0\n\t" + "shari %0, 32, %0" +#endif : "=r" (x) : "0" (x)); + return x; } -static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x) +static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) { - __asm__("swap.b %0, %0" + __asm__( +#ifdef CONFIG_SUPERH32 + "swap.b %0, %0" +#else + "byterev %0, %0\n\t" + "shari %0, 32, %0" + +#endif : "=r" (x) : "0" (x)); + return x; } -static inline __u64 ___arch__swab64(__u64 val) -{ - union { +static inline __u64 ___arch__swab64(__u64 val) +{ + union { struct { __u32 a,b; } s; __u64 u; } v, w; v.u = val; - w.s.b = ___arch__swab32(v.s.a); - w.s.a = ___arch__swab32(v.s.b); - return w.u; -} + w.s.b = ___arch__swab32(v.s.a); + w.s.a = ___arch__swab32(v.s.b); + return w.u; +} #define __arch__swab64(x) ___arch__swab64(x) #define __arch__swab32(x) ___arch__swab32(x) diff -puN include/asm-sh/cache.h~git-sh include/asm-sh/cache.h --- a/include/asm-sh/cache.h~git-sh +++ a/include/asm-sh/cache.h @@ -12,11 +12,6 @@ #include #include -#define SH_CACHE_VALID 1 -#define SH_CACHE_UPDATED 2 -#define SH_CACHE_COMBINED 4 -#define SH_CACHE_ASSOC 8 - #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) #define __read_mostly __attribute__((__section__(".data.read_mostly"))) diff -puN include/asm-sh/checksum.h~git-sh include/asm-sh/checksum.h --- a/include/asm-sh/checksum.h~git-sh +++ a/include/asm-sh/checksum.h @@ -1,215 +1,5 @@ -#ifndef __ASM_SH_CHECKSUM_H -#define __ASM_SH_CHECKSUM_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka - */ - -#include - -/* - * 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 - */ -asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * the same as csum_partial, but copies from src while it - * checksums, and handles user-space pointer exceptions correctly, when needed. - * - * here even more important to align src and dst on a 32-bit (or even - * better 64-bit) boundary - */ - -asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, - int len, __wsum sum, - int *src_err_ptr, int *dst_err_ptr); - -/* - * Note: when you get a NULL pointer exception here this means someone - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the - * access_ok(). - */ -static inline -__wsum csum_partial_copy_nocheck(const void *src, void *dst, - int len, __wsum sum) -{ - return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); -} - -static inline -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *err_ptr) -{ - return csum_partial_copy_generic((__force const void *)src, dst, - len, sum, err_ptr, NULL); -} - -/* - * Fold a partial checksum - */ - -static inline __sum16 csum_fold(__wsum sum) -{ - unsigned int __dummy; - __asm__("swap.w %0, %1\n\t" - "extu.w %0, %0\n\t" - "extu.w %1, %1\n\t" - "add %1, %0\n\t" - "swap.w %0, %1\n\t" - "add %1, %0\n\t" - "not %0, %0\n\t" - : "=r" (sum), "=&r" (__dummy) - : "0" (sum) - : "t"); - return (__force __sum16)sum; -} - -/* - * This is a version of ip_compute_csum() optimized for IP headers, - * which always checksum on 4 octet boundaries. - * - * i386 version by Jorge Cwik , adapted - * for linux by * Arnt Gulbrandsen. - */ -static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) -{ - unsigned int sum, __dummy0, __dummy1; - - __asm__ __volatile__( - "mov.l @%1+, %0\n\t" - "mov.l @%1+, %3\n\t" - "add #-2, %2\n\t" - "clrt\n\t" - "1:\t" - "addc %3, %0\n\t" - "movt %4\n\t" - "mov.l @%1+, %3\n\t" - "dt %2\n\t" - "bf/s 1b\n\t" - " cmp/eq #1, %4\n\t" - "addc %3, %0\n\t" - "addc %2, %0" /* Here %2 is 0, add carry-bit */ - /* Since the input registers which are loaded with iph and ihl - are modified, we must also specify them as outputs, or gcc - will assume they contain their original values. */ - : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (__dummy0), "=&z" (__dummy1) - : "1" (iph), "2" (ihl) - : "t"); - - return csum_fold(sum); -} - -static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ -#ifdef __LITTLE_ENDIAN__ - unsigned long len_proto = (proto + len) << 8; +#ifdef CONFIG_SUPERH32 +# include "checksum_32.h" #else - unsigned long len_proto = proto + len; +# include "checksum_64.h" #endif - __asm__("clrt\n\t" - "addc %0, %1\n\t" - "addc %2, %1\n\t" - "addc %3, %1\n\t" - "movt %0\n\t" - "add %1, %0" - : "=r" (sum), "=r" (len_proto) - : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum) - : "t"); - - return sum; -} - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -static inline __sum16 ip_compute_csum(const void *buff, int len) -{ - return csum_fold(csum_partial(buff, len, 0)); -} - -#define _HAVE_ARCH_IPV6_CSUM -static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, - const struct in6_addr *daddr, - __u32 len, unsigned short proto, - __wsum sum) -{ - unsigned int __dummy; - __asm__("clrt\n\t" - "mov.l @(0,%2), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(4,%2), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(8,%2), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(12,%2), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(0,%3), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(4,%3), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(8,%3), %1\n\t" - "addc %1, %0\n\t" - "mov.l @(12,%3), %1\n\t" - "addc %1, %0\n\t" - "addc %4, %0\n\t" - "addc %5, %0\n\t" - "movt %1\n\t" - "add %1, %0\n" - : "=r" (sum), "=&r" (__dummy) - : "r" (saddr), "r" (daddr), - "r" (htonl(len)), "r" (htonl(proto)), "0" (sum) - : "t"); - - return csum_fold(sum); -} - -/* - * Copy and checksum to user - */ -#define HAVE_CSUM_COPY_USER -static inline __wsum csum_and_copy_to_user(const void *src, - void __user *dst, - int len, __wsum sum, - int *err_ptr) -{ - if (access_ok(VERIFY_WRITE, dst, len)) - return csum_partial_copy_generic((__force const void *)src, - dst, len, sum, NULL, err_ptr); - - if (len) - *err_ptr = -EFAULT; - - return (__force __wsum)-1; /* invalid checksum */ -} -#endif /* __ASM_SH_CHECKSUM_H */ diff -puN /dev/null include/asm-sh/checksum_32.h --- /dev/null +++ a/include/asm-sh/checksum_32.h @@ -0,0 +1,215 @@ +#ifndef __ASM_SH_CHECKSUM_H +#define __ASM_SH_CHECKSUM_H + +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 1999 by Kaz Kojima & Niibe Yutaka + */ + +#include + +/* + * 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 + */ +asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum); + +/* + * the same as csum_partial, but copies from src while it + * checksums, and handles user-space pointer exceptions correctly, when needed. + * + * here even more important to align src and dst on a 32-bit (or even + * better 64-bit) boundary + */ + +asmlinkage __wsum csum_partial_copy_generic(const void *src, void *dst, + int len, __wsum sum, + int *src_err_ptr, int *dst_err_ptr); + +/* + * Note: when you get a NULL pointer exception here this means someone + * passed in an incorrect kernel address to one of these functions. + * + * If you use these functions directly please don't forget the + * access_ok(). + */ +static inline +__wsum csum_partial_copy_nocheck(const void *src, void *dst, + int len, __wsum sum) +{ + return csum_partial_copy_generic(src, dst, len, sum, NULL, NULL); +} + +static inline +__wsum csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *err_ptr) +{ + return csum_partial_copy_generic((__force const void *)src, dst, + len, sum, err_ptr, NULL); +} + +/* + * Fold a partial checksum + */ + +static inline __sum16 csum_fold(__wsum sum) +{ + unsigned int __dummy; + __asm__("swap.w %0, %1\n\t" + "extu.w %0, %0\n\t" + "extu.w %1, %1\n\t" + "add %1, %0\n\t" + "swap.w %0, %1\n\t" + "add %1, %0\n\t" + "not %0, %0\n\t" + : "=r" (sum), "=&r" (__dummy) + : "0" (sum) + : "t"); + return (__force __sum16)sum; +} + +/* + * This is a version of ip_compute_csum() optimized for IP headers, + * which always checksum on 4 octet boundaries. + * + * i386 version by Jorge Cwik , adapted + * for linux by * Arnt Gulbrandsen. + */ +static inline __sum16 ip_fast_csum(const void *iph, unsigned int ihl) +{ + unsigned int sum, __dummy0, __dummy1; + + __asm__ __volatile__( + "mov.l @%1+, %0\n\t" + "mov.l @%1+, %3\n\t" + "add #-2, %2\n\t" + "clrt\n\t" + "1:\t" + "addc %3, %0\n\t" + "movt %4\n\t" + "mov.l @%1+, %3\n\t" + "dt %2\n\t" + "bf/s 1b\n\t" + " cmp/eq #1, %4\n\t" + "addc %3, %0\n\t" + "addc %2, %0" /* Here %2 is 0, add carry-bit */ + /* Since the input registers which are loaded with iph and ihl + are modified, we must also specify them as outputs, or gcc + will assume they contain their original values. */ + : "=r" (sum), "=r" (iph), "=r" (ihl), "=&r" (__dummy0), "=&z" (__dummy1) + : "1" (iph), "2" (ihl) + : "t"); + + return csum_fold(sum); +} + +static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, + __wsum sum) +{ +#ifdef __LITTLE_ENDIAN__ + unsigned long len_proto = (proto + len) << 8; +#else + unsigned long len_proto = proto + len; +#endif + __asm__("clrt\n\t" + "addc %0, %1\n\t" + "addc %2, %1\n\t" + "addc %3, %1\n\t" + "movt %0\n\t" + "add %1, %0" + : "=r" (sum), "=r" (len_proto) + : "r" (daddr), "r" (saddr), "1" (len_proto), "0" (sum) + : "t"); + + return sum; +} + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, + __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline __sum16 ip_compute_csum(const void *buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#define _HAVE_ARCH_IPV6_CSUM +static inline __sum16 csum_ipv6_magic(const struct in6_addr *saddr, + const struct in6_addr *daddr, + __u32 len, unsigned short proto, + __wsum sum) +{ + unsigned int __dummy; + __asm__("clrt\n\t" + "mov.l @(0,%2), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(4,%2), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(8,%2), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(12,%2), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(0,%3), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(4,%3), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(8,%3), %1\n\t" + "addc %1, %0\n\t" + "mov.l @(12,%3), %1\n\t" + "addc %1, %0\n\t" + "addc %4, %0\n\t" + "addc %5, %0\n\t" + "movt %1\n\t" + "add %1, %0\n" + : "=r" (sum), "=&r" (__dummy) + : "r" (saddr), "r" (daddr), + "r" (htonl(len)), "r" (htonl(proto)), "0" (sum) + : "t"); + + return csum_fold(sum); +} + +/* + * Copy and checksum to user + */ +#define HAVE_CSUM_COPY_USER +static inline __wsum csum_and_copy_to_user(const void *src, + void __user *dst, + int len, __wsum sum, + int *err_ptr) +{ + if (access_ok(VERIFY_WRITE, dst, len)) + return csum_partial_copy_generic((__force const void *)src, + dst, len, sum, NULL, err_ptr); + + if (len) + *err_ptr = -EFAULT; + + return (__force __wsum)-1; /* invalid checksum */ +} +#endif /* __ASM_SH_CHECKSUM_H */ diff -puN /dev/null include/asm-sh/checksum_64.h --- /dev/null +++ a/include/asm-sh/checksum_64.h @@ -0,0 +1,78 @@ +#ifndef __ASM_SH_CHECKSUM_64_H +#define __ASM_SH_CHECKSUM_64_H + +/* + * include/asm-sh/checksum_64.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +/* + * 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 + */ +asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum); + +/* + * Note: when you get a NULL pointer exception here this means someone + * passed in an incorrect kernel address to one of these functions. + * + * If you use these functions directly please don't forget the + * access_ok(). + */ + + +__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, + __wsum sum); + +__wsum csum_partial_copy_from_user(const void __user *src, void *dst, + int len, __wsum sum, int *err_ptr); + +static inline __sum16 csum_fold(__wsum csum) +{ + u32 sum = (__force u32)csum; + sum = (sum & 0xffff) + (sum >> 16); + sum = (sum & 0xffff) + (sum >> 16); + return (__force __sum16)~sum; +} + +__sum16 ip_fast_csum(const void *iph, unsigned int ihl); + +__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, + unsigned short len, unsigned short proto, + __wsum sum); + +/* + * computes the checksum of the TCP/UDP pseudo-header + * returns a 16-bit checksum, already complemented + */ +static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, + unsigned short len, + unsigned short proto, + __wsum sum) +{ + return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); +} + +/* + * this routine is used for miscellaneous IP-like checksums, mainly + * in icmp.c + */ +static inline __sum16 ip_compute_csum(const void *buff, int len) +{ + return csum_fold(csum_partial(buff, len, 0)); +} + +#endif /* __ASM_SH_CHECKSUM_64_H */ diff -puN /dev/null include/asm-sh/cmpxchg-grb.h --- /dev/null +++ a/include/asm-sh/cmpxchg-grb.h @@ -0,0 +1,70 @@ +#ifndef __ASM_SH_CMPXCHG_GRB_H +#define __ASM_SH_CMPXCHG_GRB_H + +static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) +{ + unsigned long retval; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " nop \n\t" + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-4, r15 \n\t" /* LOGIN */ + " mov.l @%1, %0 \n\t" /* load old value */ + " mov.l %2, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (retval), + "+r" (m) + : "r" (val) + : "memory", "r0", "r1"); + + return retval; +} + +static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) +{ + unsigned long retval; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-6, r15 \n\t" /* LOGIN */ + " mov.b @%1, %0 \n\t" /* load old value */ + " extu.b %0, %0 \n\t" /* extend as unsigned */ + " mov.b %2, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (retval), + "+r" (m) + : "r" (val) + : "memory" , "r0", "r1"); + + return retval; +} + +static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, + unsigned long new) +{ + unsigned long retval; + + __asm__ __volatile__ ( + " .align 2 \n\t" + " mova 1f, r0 \n\t" /* r0 = end point */ + " nop \n\t" + " mov r15, r1 \n\t" /* r1 = saved sp */ + " mov #-8, r15 \n\t" /* LOGIN */ + " mov.l @%1, %0 \n\t" /* load old value */ + " cmp/eq %0, %2 \n\t" + " bf 1f \n\t" /* if not equal */ + " mov.l %2, @%1 \n\t" /* store new value */ + "1: mov r1, r15 \n\t" /* LOGOUT */ + : "=&r" (retval), + "+r" (m) + : "r" (new) + : "memory" , "r0", "r1", "t"); + + return retval; +} + +#endif /* __ASM_SH_CMPXCHG_GRB_H */ diff -puN /dev/null include/asm-sh/cmpxchg-irq.h --- /dev/null +++ a/include/asm-sh/cmpxchg-irq.h @@ -0,0 +1,40 @@ +#ifndef __ASM_SH_CMPXCHG_IRQ_H +#define __ASM_SH_CMPXCHG_IRQ_H + +static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) +{ + unsigned long flags, retval; + + local_irq_save(flags); + retval = *m; + *m = val; + local_irq_restore(flags); + return retval; +} + +static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) +{ + unsigned long flags, retval; + + local_irq_save(flags); + retval = *m; + *m = val & 0xff; + local_irq_restore(flags); + return retval; +} + +static inline unsigned long __cmpxchg_u32(volatile int *m, unsigned long old, + unsigned long new) +{ + __u32 retval; + unsigned long flags; + + local_irq_save(flags); + retval = *m; + if (retval == old) + *m = new; + local_irq_restore(flags); /* implies memory barrier */ + return retval; +} + +#endif /* __ASM_SH_CMPXCHG_IRQ_H */ diff -puN include/asm-sh/cpu-sh2/addrspace.h~git-sh include/asm-sh/cpu-sh2/addrspace.h --- a/include/asm-sh/cpu-sh2/addrspace.h~git-sh +++ a/include/asm-sh/cpu-sh2/addrspace.h @@ -10,7 +10,10 @@ #ifndef __ASM_CPU_SH2_ADDRSPACE_H #define __ASM_CPU_SH2_ADDRSPACE_H -/* Should fill here */ +#define P0SEG 0x00000000 +#define P1SEG 0x80000000 +#define P2SEG 0xa0000000 +#define P3SEG 0xc0000000 +#define P4SEG 0xe0000000 #endif /* __ASM_CPU_SH2_ADDRSPACE_H */ - diff -puN include/asm-sh/cpu-sh2/cache.h~git-sh include/asm-sh/cpu-sh2/cache.h --- a/include/asm-sh/cpu-sh2/cache.h~git-sh +++ a/include/asm-sh/cpu-sh2/cache.h @@ -12,9 +12,13 @@ #define L1_CACHE_SHIFT 4 +#define SH_CACHE_VALID 1 +#define SH_CACHE_UPDATED 2 +#define SH_CACHE_COMBINED 4 +#define SH_CACHE_ASSOC 8 + #if defined(CONFIG_CPU_SUBTYPE_SH7619) -#define CCR1 0xffffffec -#define CCR CCR1 +#define CCR 0xffffffec #define CCR_CACHE_CE 0x01 /* Cache enable */ #define CCR_CACHE_WT 0x06 /* CCR[bit1=1,bit2=1] */ diff -puN /dev/null include/asm-sh/cpu-sh2/rtc.h --- /dev/null +++ a/include/asm-sh/cpu-sh2/rtc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_SH_CPU_SH2_RTC_H +#define __ASM_SH_CPU_SH2_RTC_H + +#define rtc_reg_size sizeof(u16) +#define RTC_BIT_INVERTED 0 +#define RTC_DEF_CAPABILITIES 0UL + +#endif /* __ASM_SH_CPU_SH2_RTC_H */ diff -puN include/asm-sh/cpu-sh2a/addrspace.h~git-sh include/asm-sh/cpu-sh2a/addrspace.h --- a/include/asm-sh/cpu-sh2a/addrspace.h~git-sh +++ a/include/asm-sh/cpu-sh2a/addrspace.h @@ -1 +1,10 @@ -#include +#ifndef __ASM_SH_CPU_SH2A_ADDRSPACE_H +#define __ASM_SH_CPU_SH2A_ADDRSPACE_H + +#define P0SEG 0x00000000 +#define P1SEG 0x00000000 +#define P2SEG 0x20000000 +#define P3SEG 0x00000000 +#define P4SEG 0x80000000 + +#endif /* __ASM_SH_CPU_SH2A_ADDRSPACE_H */ diff -puN include/asm-sh/cpu-sh2a/cache.h~git-sh include/asm-sh/cpu-sh2a/cache.h --- a/include/asm-sh/cpu-sh2a/cache.h~git-sh +++ a/include/asm-sh/cpu-sh2a/cache.h @@ -12,11 +12,13 @@ #define L1_CACHE_SHIFT 4 -#define CCR1 0xfffc1000 -#define CCR2 0xfffc1004 +#define SH_CACHE_VALID 1 +#define SH_CACHE_UPDATED 2 +#define SH_CACHE_COMBINED 4 +#define SH_CACHE_ASSOC 8 -/* CCR1 behaves more like the traditional CCR */ -#define CCR CCR1 +#define CCR 0xfffc1000 /* CCR1 */ +#define CCR2 0xfffc1004 /* * Most of the SH-2A CCR1 definitions resemble the SH-4 ones. All others not @@ -36,4 +38,3 @@ #define CCR_CACHE_INVALIDATE (CCR_CACHE_OCI | CCR_CACHE_ICI) #endif /* __ASM_CPU_SH2A_CACHE_H */ - diff -puN include/asm-sh/cpu-sh2a/freq.h~git-sh include/asm-sh/cpu-sh2a/freq.h --- a/include/asm-sh/cpu-sh2a/freq.h~git-sh +++ a/include/asm-sh/cpu-sh2a/freq.h @@ -10,9 +10,7 @@ #ifndef __ASM_CPU_SH2A_FREQ_H #define __ASM_CPU_SH2A_FREQ_H -#if defined(CONFIG_CPU_SUBTYPE_SH7206) #define FREQCR 0xfffe0010 -#endif #endif /* __ASM_CPU_SH2A_FREQ_H */ diff -puN /dev/null include/asm-sh/cpu-sh2a/rtc.h --- /dev/null +++ a/include/asm-sh/cpu-sh2a/rtc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_SH_CPU_SH2A_RTC_H +#define __ASM_SH_CPU_SH2A_RTC_H + +#define rtc_reg_size sizeof(u16) +#define RTC_BIT_INVERTED 0 +#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR + +#endif /* __ASM_SH_CPU_SH2A_RTC_H */ diff -puN include/asm-sh/cpu-sh3/addrspace.h~git-sh include/asm-sh/cpu-sh3/addrspace.h --- a/include/asm-sh/cpu-sh3/addrspace.h~git-sh +++ a/include/asm-sh/cpu-sh3/addrspace.h @@ -10,7 +10,10 @@ #ifndef __ASM_CPU_SH3_ADDRSPACE_H #define __ASM_CPU_SH3_ADDRSPACE_H -/* Should fill here */ +#define P0SEG 0x00000000 +#define P1SEG 0x80000000 +#define P2SEG 0xa0000000 +#define P3SEG 0xc0000000 +#define P4SEG 0xe0000000 #endif /* __ASM_CPU_SH3_ADDRSPACE_H */ - diff -puN include/asm-sh/cpu-sh3/cache.h~git-sh include/asm-sh/cpu-sh3/cache.h --- a/include/asm-sh/cpu-sh3/cache.h~git-sh +++ a/include/asm-sh/cpu-sh3/cache.h @@ -12,6 +12,11 @@ #define L1_CACHE_SHIFT 4 +#define SH_CACHE_VALID 1 +#define SH_CACHE_UPDATED 2 +#define SH_CACHE_COMBINED 4 +#define SH_CACHE_ASSOC 8 + #define CCR 0xffffffec /* Address of Cache Control Register */ #define CCR_CACHE_CE 0x01 /* Cache Enable */ diff -puN /dev/null include/asm-sh/cpu-sh3/rtc.h --- /dev/null +++ a/include/asm-sh/cpu-sh3/rtc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_SH_CPU_SH3_RTC_H +#define __ASM_SH_CPU_SH3_RTC_H + +#define rtc_reg_size sizeof(u16) +#define RTC_BIT_INVERTED 0 /* No bug on SH7708, SH7709A */ +#define RTC_DEF_CAPABILITIES 0UL + +#endif /* __ASM_SH_CPU_SH3_RTC_H */ diff -puN include/asm-sh/cpu-sh4/addrspace.h~git-sh include/asm-sh/cpu-sh4/addrspace.h --- a/include/asm-sh/cpu-sh4/addrspace.h~git-sh +++ a/include/asm-sh/cpu-sh4/addrspace.h @@ -10,6 +10,12 @@ #ifndef __ASM_CPU_SH4_ADDRSPACE_H #define __ASM_CPU_SH4_ADDRSPACE_H +#define P0SEG 0x00000000 +#define P1SEG 0x80000000 +#define P2SEG 0xa0000000 +#define P3SEG 0xc0000000 +#define P4SEG 0xe0000000 + /* Detailed P4SEG */ #define P4SEG_STORE_QUE (P4SEG) #define P4SEG_IC_ADDR 0xf0000000 diff -puN include/asm-sh/cpu-sh4/cache.h~git-sh include/asm-sh/cpu-sh4/cache.h --- a/include/asm-sh/cpu-sh4/cache.h~git-sh +++ a/include/asm-sh/cpu-sh4/cache.h @@ -12,6 +12,11 @@ #define L1_CACHE_SHIFT 5 +#define SH_CACHE_VALID 1 +#define SH_CACHE_UPDATED 2 +#define SH_CACHE_COMBINED 4 +#define SH_CACHE_ASSOC 8 + #define CCR 0xff00001c /* Address of Cache Control Register */ #define CCR_CACHE_OCE 0x0001 /* Operand Cache Enable */ #define CCR_CACHE_WT 0x0002 /* Write-Through (for P0,U0,P3) (else writeback)*/ diff -puN /dev/null include/asm-sh/cpu-sh4/fpu.h --- /dev/null +++ a/include/asm-sh/cpu-sh4/fpu.h @@ -0,0 +1,32 @@ +/* + * linux/arch/sh/kernel/cpu/sh4/sh4_fpu.h + * + * Copyright (C) 2006 STMicroelectronics Limited + * Author: Carl Shaw + * + * May be copied or modified under the terms of the GNU General Public + * License Version 2. See linux/COPYING for more information. + * + * Definitions for SH4 FPU operations + */ + +#ifndef __CPU_SH4_FPU_H +#define __CPU_SH4_FPU_H + +#define FPSCR_ENABLE_MASK 0x00000f80UL + +#define FPSCR_FMOV_DOUBLE (1<<1) + +#define FPSCR_CAUSE_INEXACT (1<<12) +#define FPSCR_CAUSE_UNDERFLOW (1<<13) +#define FPSCR_CAUSE_OVERFLOW (1<<14) +#define FPSCR_CAUSE_DIVZERO (1<<15) +#define FPSCR_CAUSE_INVALID (1<<16) +#define FPSCR_CAUSE_ERROR (1<<17) + +#define FPSCR_DBL_PRECISION (1<<19) +#define FPSCR_ROUNDING_MODE(x) ((x >> 20) & 3) +#define FPSCR_RM_NEAREST (0) +#define FPSCR_RM_ZERO (1) + +#endif diff -puN include/asm-sh/cpu-sh4/mmu_context.h~git-sh include/asm-sh/cpu-sh4/mmu_context.h --- a/include/asm-sh/cpu-sh4/mmu_context.h~git-sh +++ a/include/asm-sh/cpu-sh4/mmu_context.h @@ -22,12 +22,20 @@ #define MMU_UTLB_ADDRESS_ARRAY 0xF6000000 #define MMU_PAGE_ASSOC_BIT 0x80 +#define MMUCR_TI (1<<2) + #ifdef CONFIG_X2TLB #define MMUCR_ME (1 << 7) #else #define MMUCR_ME (0) #endif +#if defined(CONFIG_32BIT) && defined(CONFIG_CPU_SUBTYPE_ST40) +#define MMUCR_SE (1 << 4) +#else +#define MMUCR_SE (0) +#endif + #ifdef CONFIG_SH_STORE_QUEUES #define MMUCR_SQMD (1 << 9) #else @@ -35,7 +43,7 @@ #endif #define MMU_NTLB_ENTRIES 64 -#define MMU_CONTROL_INIT (0x05|MMUCR_SQMD|MMUCR_ME) +#define MMU_CONTROL_INIT (0x05|MMUCR_SQMD|MMUCR_ME|MMUCR_SE) #define MMU_ITLB_DATA_ARRAY 0xF3000000 #define MMU_UTLB_DATA_ARRAY 0xF7000000 diff -puN /dev/null include/asm-sh/cpu-sh4/rtc.h --- /dev/null +++ a/include/asm-sh/cpu-sh4/rtc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_SH_CPU_SH4_RTC_H +#define __ASM_SH_CPU_SH4_RTC_H + +#define rtc_reg_size sizeof(u32) +#define RTC_BIT_INVERTED 0x40 /* bug on SH7750, SH7750S */ +#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR + +#endif /* __ASM_SH_CPU_SH4_RTC_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/addrspace.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/addrspace.h @@ -0,0 +1,11 @@ +#ifndef __ASM_SH_CPU_SH5_ADDRSPACE_H +#define __ASM_SH_CPU_SH5_ADDRSPACE_H + +#define PHYS_PERIPHERAL_BLOCK 0x09000000 +#define PHYS_DMAC_BLOCK 0x0e000000 +#define PHYS_PCI_BLOCK 0x60000000 +#define PHYS_EMI_BLOCK 0xff000000 + +/* No segmentation.. */ + +#endif /* __ASM_SH_CPU_SH5_ADDRSPACE_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/cache.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/cache.h @@ -0,0 +1,97 @@ +#ifndef __ASM_SH_CPU_SH5_CACHE_H +#define __ASM_SH_CPU_SH5_CACHE_H + +/* + * include/asm-sh/cpu-sh5/cache.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#define L1_CACHE_SHIFT 5 + +/* Valid and Dirty bits */ +#define SH_CACHE_VALID (1LL<<0) +#define SH_CACHE_UPDATED (1LL<<57) + +/* Unimplemented compat bits.. */ +#define SH_CACHE_COMBINED 0 +#define SH_CACHE_ASSOC 0 + +/* Cache flags */ +#define SH_CACHE_MODE_WT (1LL<<0) +#define SH_CACHE_MODE_WB (1LL<<1) + +/* + * Control Registers. + */ +#define ICCR_BASE 0x01600000 /* Instruction Cache Control Register */ +#define ICCR_REG0 0 /* Register 0 offset */ +#define ICCR_REG1 1 /* Register 1 offset */ +#define ICCR0 ICCR_BASE+ICCR_REG0 +#define ICCR1 ICCR_BASE+ICCR_REG1 + +#define ICCR0_OFF 0x0 /* Set ICACHE off */ +#define ICCR0_ON 0x1 /* Set ICACHE on */ +#define ICCR0_ICI 0x2 /* Invalidate all in IC */ + +#define ICCR1_NOLOCK 0x0 /* Set No Locking */ + +#define OCCR_BASE 0x01E00000 /* Operand Cache Control Register */ +#define OCCR_REG0 0 /* Register 0 offset */ +#define OCCR_REG1 1 /* Register 1 offset */ +#define OCCR0 OCCR_BASE+OCCR_REG0 +#define OCCR1 OCCR_BASE+OCCR_REG1 + +#define OCCR0_OFF 0x0 /* Set OCACHE off */ +#define OCCR0_ON 0x1 /* Set OCACHE on */ +#define OCCR0_OCI 0x2 /* Invalidate all in OC */ +#define OCCR0_WT 0x4 /* Set OCACHE in WT Mode */ +#define OCCR0_WB 0x0 /* Set OCACHE in WB Mode */ + +#define OCCR1_NOLOCK 0x0 /* Set No Locking */ + +/* + * SH-5 + * A bit of description here, for neff=32. + * + * |<--- tag (19 bits) --->| + * +-----------------------------+-----------------+------+----------+------+ + * | | | ways |set index |offset| + * +-----------------------------+-----------------+------+----------+------+ + * ^ 2 bits 8 bits 5 bits + * +- Bit 31 + * + * Cacheline size is based on offset: 5 bits = 32 bytes per line + * A cache line is identified by a tag + set but OCACHETAG/ICACHETAG + * have a broader space for registers. These are outlined by + * CACHE_?C_*_STEP below. + * + */ + +/* Instruction cache */ +#define CACHE_IC_ADDRESS_ARRAY 0x01000000 + +/* Operand Cache */ +#define CACHE_OC_ADDRESS_ARRAY 0x01800000 + +/* These declarations relate to cache 'synonyms' in the operand cache. A + 'synonym' occurs where effective address bits overlap between those used for + indexing the cache sets and those passed to the MMU for translation. In the + case of SH5-101 & SH5-103, only bit 12 is affected for 4k pages. */ + +#define CACHE_OC_N_SYNBITS 1 /* Number of synonym bits */ +#define CACHE_OC_SYN_SHIFT 12 +/* Mask to select synonym bit(s) */ +#define CACHE_OC_SYN_MASK (((1UL< + +struct vm_area_struct; +struct page; +struct mm_struct; + +extern void flush_cache_all(void); +extern void flush_cache_mm(struct mm_struct *mm); +extern void flush_cache_sigtramp(unsigned long start, unsigned long end); +extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, + unsigned long end); +extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); +extern void flush_dcache_page(struct page *pg); +extern void flush_icache_range(unsigned long start, unsigned long end); +extern void flush_icache_user_range(struct vm_area_struct *vma, + struct page *page, unsigned long addr, + int len); + +#define flush_cache_dup_mm(mm) flush_cache_mm(mm) + +#define flush_dcache_mmap_lock(mapping) do { } while (0) +#define flush_dcache_mmap_unlock(mapping) do { } while (0) + +#define flush_icache_page(vma, page) do { } while (0) +#define p3_cache_init() do { } while (0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_SH_CPU_SH5_CACHEFLUSH_H */ + diff -puN /dev/null include/asm-sh/cpu-sh5/dma.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/dma.h @@ -0,0 +1,6 @@ +#ifndef __ASM_SH_CPU_SH5_DMA_H +#define __ASM_SH_CPU_SH5_DMA_H + +/* Nothing yet */ + +#endif /* __ASM_SH_CPU_SH5_DMA_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/irq.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/irq.h @@ -0,0 +1,117 @@ +#ifndef __ASM_SH_CPU_SH5_IRQ_H +#define __ASM_SH_CPU_SH5_IRQ_H + +/* + * include/asm-sh/cpu-sh5/irq.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + + +/* + * Encoded IRQs are not considered worth to be supported. + * Main reason is that there's no per-encoded-interrupt + * enable/disable mechanism (as there was in SH3/4). + * An all enabled/all disabled is worth only if there's + * a cascaded IC to disable/enable/ack on. Until such + * IC is available there's no such support. + * + * Presumably Encoded IRQs may use extra IRQs beyond 64, + * below. Some logic must be added to cope with IRQ_IRL? + * in an exclusive way. + * + * Priorities are set at Platform level, when IRQ_IRL0-3 + * are set to 0 Encoding is allowed. Otherwise it's not + * allowed. + */ + +/* Independent IRQs */ +#define IRQ_IRL0 0 +#define IRQ_IRL1 1 +#define IRQ_IRL2 2 +#define IRQ_IRL3 3 + +#define IRQ_INTA 4 +#define IRQ_INTB 5 +#define IRQ_INTC 6 +#define IRQ_INTD 7 + +#define IRQ_SERR 12 +#define IRQ_ERR 13 +#define IRQ_PWR3 14 +#define IRQ_PWR2 15 +#define IRQ_PWR1 16 +#define IRQ_PWR0 17 + +#define IRQ_DMTE0 18 +#define IRQ_DMTE1 19 +#define IRQ_DMTE2 20 +#define IRQ_DMTE3 21 +#define IRQ_DAERR 22 + +#define IRQ_TUNI0 32 +#define IRQ_TUNI1 33 +#define IRQ_TUNI2 34 +#define IRQ_TICPI2 35 + +#define IRQ_ATI 36 +#define IRQ_PRI 37 +#define IRQ_CUI 38 + +#define IRQ_ERI 39 +#define IRQ_RXI 40 +#define IRQ_BRI 41 +#define IRQ_TXI 42 + +#define IRQ_ITI 63 + +#define NR_INTC_IRQS 64 + +#ifdef CONFIG_SH_CAYMAN +#define NR_EXT_IRQS 32 +#define START_EXT_IRQS 64 + +/* PCI bus 2 uses encoded external interrupts on the Cayman board */ +#define IRQ_P2INTA (START_EXT_IRQS + (3*8) + 0) +#define IRQ_P2INTB (START_EXT_IRQS + (3*8) + 1) +#define IRQ_P2INTC (START_EXT_IRQS + (3*8) + 2) +#define IRQ_P2INTD (START_EXT_IRQS + (3*8) + 3) + +#define I8042_KBD_IRQ (START_EXT_IRQS + 2) +#define I8042_AUX_IRQ (START_EXT_IRQS + 6) + +#define IRQ_CFCARD (START_EXT_IRQS + 7) +#define IRQ_PCMCIA (0) + +#else +#define NR_EXT_IRQS 0 +#endif + +/* Default IRQs, fixed */ +#define TIMER_IRQ IRQ_TUNI0 +#define RTC_IRQ IRQ_CUI + +/* Default Priorities, Platform may choose differently */ +#define NO_PRIORITY 0 /* Disabled */ +#define TIMER_PRIORITY 2 +#define RTC_PRIORITY TIMER_PRIORITY +#define SCIF_PRIORITY 3 +#define INTD_PRIORITY 3 +#define IRL3_PRIORITY 4 +#define INTC_PRIORITY 6 +#define IRL2_PRIORITY 7 +#define INTB_PRIORITY 9 +#define IRL1_PRIORITY 10 +#define INTA_PRIORITY 12 +#define IRL0_PRIORITY 13 +#define TOP_PRIORITY 15 + +extern int intc_evt_to_irq[(0xE20/0x20)+1]; +int intc_irq_describe(char* p, int irq); +extern int platform_int_priority[NR_INTC_IRQS]; + +#endif /* __ASM_SH_CPU_SH5_IRQ_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/mmu_context.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/mmu_context.h @@ -0,0 +1,27 @@ +#ifndef __ASM_SH_CPU_SH5_MMU_CONTEXT_H +#define __ASM_SH_CPU_SH5_MMU_CONTEXT_H + +/* Common defines */ +#define TLB_STEP 0x00000010 +#define TLB_PTEH 0x00000000 +#define TLB_PTEL 0x00000008 + +/* PTEH defines */ +#define PTEH_ASID_SHIFT 2 +#define PTEH_VALID 0x0000000000000001 +#define PTEH_SHARED 0x0000000000000002 +#define PTEH_MATCH_ASID 0x00000000000003ff + +#ifndef __ASSEMBLY__ +/* This has to be a common function because the next location to fill + * information is shared. */ +extern void __do_tlb_refill(unsigned long address, unsigned long long is_text_not_data, pte_t *pte); + +/* Profiling counter. */ +#ifdef CONFIG_SH64_PROC_TLB +extern unsigned long long calls_to_do_fast_page_fault; +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_SH_CPU_SH5_MMU_CONTEXT_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/registers.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/registers.h @@ -0,0 +1,106 @@ +#ifndef __ASM_SH_CPU_SH5_REGISTERS_H +#define __ASM_SH_CPU_SH5_REGISTERS_H + +/* + * include/asm-sh/cpu-sh5/registers.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#ifdef __ASSEMBLY__ +/* ===================================================================== +** +** Section 1: acts on assembly sources pre-processed by GPP ( ). +** Assigns symbolic names to control & target registers. +*/ + +/* + * Define some useful aliases for control registers. + */ +#define SR cr0 +#define SSR cr1 +#define PSSR cr2 + /* cr3 UNDEFINED */ +#define INTEVT cr4 +#define EXPEVT cr5 +#define PEXPEVT cr6 +#define TRA cr7 +#define SPC cr8 +#define PSPC cr9 +#define RESVEC cr10 +#define VBR cr11 + /* cr12 UNDEFINED */ +#define TEA cr13 + /* cr14-cr15 UNDEFINED */ +#define DCR cr16 +#define KCR0 cr17 +#define KCR1 cr18 + /* cr19-cr31 UNDEFINED */ + /* cr32-cr61 RESERVED */ +#define CTC cr62 +#define USR cr63 + +/* + * ABI dependent registers (general purpose set) + */ +#define RET r2 +#define ARG1 r2 +#define ARG2 r3 +#define ARG3 r4 +#define ARG4 r5 +#define ARG5 r6 +#define ARG6 r7 +#define SP r15 +#define LINK r18 +#define ZERO r63 + +/* + * Status register defines: used only by assembly sources (and + * syntax independednt) + */ +#define SR_RESET_VAL 0x0000000050008000 +#define SR_HARMLESS 0x00000000500080f0 /* Write ignores for most */ +#define SR_ENABLE_FPU 0xffffffffffff7fff /* AND with this */ + +#if defined (CONFIG_SH64_SR_WATCH) +#define SR_ENABLE_MMU 0x0000000084000000 /* OR with this */ +#else +#define SR_ENABLE_MMU 0x0000000080000000 /* OR with this */ +#endif + +#define SR_UNBLOCK_EXC 0xffffffffefffffff /* AND with this */ +#define SR_BLOCK_EXC 0x0000000010000000 /* OR with this */ + +#else /* Not __ASSEMBLY__ syntax */ + +/* +** Stringify reg. name +*/ +#define __str(x) #x + +/* Stringify control register names for use in inline assembly */ +#define __SR __str(SR) +#define __SSR __str(SSR) +#define __PSSR __str(PSSR) +#define __INTEVT __str(INTEVT) +#define __EXPEVT __str(EXPEVT) +#define __PEXPEVT __str(PEXPEVT) +#define __TRA __str(TRA) +#define __SPC __str(SPC) +#define __PSPC __str(PSPC) +#define __RESVEC __str(RESVEC) +#define __VBR __str(VBR) +#define __TEA __str(TEA) +#define __DCR __str(DCR) +#define __KCR0 __str(KCR0) +#define __KCR1 __str(KCR1) +#define __CTC __str(CTC) +#define __USR __str(USR) + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_SH_CPU_SH5_REGISTERS_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/rtc.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/rtc.h @@ -0,0 +1,8 @@ +#ifndef __ASM_SH_CPU_SH5_RTC_H +#define __ASM_SH_CPU_SH5_RTC_H + +#define rtc_reg_size sizeof(u32) +#define RTC_BIT_INVERTED 0 /* The SH-5 RTC is surprisingly sane! */ +#define RTC_DEF_CAPABILITIES RTC_CAP_4_DIGIT_YEAR + +#endif /* __ASM_SH_CPU_SH5_RTC_H */ diff -puN /dev/null include/asm-sh/cpu-sh5/timer.h --- /dev/null +++ a/include/asm-sh/cpu-sh5/timer.h @@ -0,0 +1,4 @@ +#ifndef __ASM_SH_CPU_SH5_TIMER_H +#define __ASM_SH_CPU_SH5_TIMER_H + +#endif /* __ASM_SH_CPU_SH5_TIMER_H */ diff -puN include/asm-sh/delay.h~git-sh include/asm-sh/delay.h --- a/include/asm-sh/delay.h~git-sh +++ a/include/asm-sh/delay.h @@ -6,7 +6,7 @@ * * Delay routines calling functions in arch/sh/lib/delay.c */ - + extern void __bad_udelay(void); extern void __bad_ndelay(void); @@ -15,13 +15,17 @@ extern void __ndelay(unsigned long nsecs extern void __const_udelay(unsigned long usecs); extern void __delay(unsigned long loops); +#ifdef CONFIG_SUPERH32 #define udelay(n) (__builtin_constant_p(n) ? \ ((n) > 20000 ? __bad_udelay() : __const_udelay((n) * 0x10c6ul)) : \ __udelay(n)) - #define ndelay(n) (__builtin_constant_p(n) ? \ ((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \ __ndelay(n)) +#else +extern void udelay(unsigned long usecs); +extern void ndelay(unsigned long nsecs); +#endif #endif /* __ASM_SH_DELAY_H */ diff -puN include/asm-sh/dma-mapping.h~git-sh include/asm-sh/dma-mapping.h --- a/include/asm-sh/dma-mapping.h~git-sh +++ a/include/asm-sh/dma-mapping.h @@ -10,7 +10,7 @@ extern struct bus_type pci_bus_type; /* arch/sh/mm/consistent.c */ extern void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *handle); -extern void consistent_free(void *vaddr, size_t size); +extern void consistent_free(void *vaddr, size_t size, dma_addr_t handle); extern void consistent_sync(void *vaddr, size_t size, int direction); #define dma_supported(dev, mask) (1) @@ -50,7 +50,7 @@ static inline void dma_free_coherent(str return; } - consistent_free(vaddr, size); + consistent_free(vaddr, size, dma_handle); } #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) diff -puN include/asm-sh/elf.h~git-sh include/asm-sh/elf.h --- a/include/asm-sh/elf.h~git-sh +++ a/include/asm-sh/elf.h @@ -5,7 +5,7 @@ #include #include -/* SH relocation types */ +/* SH (particularly SHcompact) relocation types */ #define R_SH_NONE 0 #define R_SH_DIR32 1 #define R_SH_REL32 2 @@ -43,6 +43,11 @@ #define R_SH_RELATIVE 165 #define R_SH_GOTOFF 166 #define R_SH_GOTPC 167 +/* SHmedia relocs */ +#define R_SH_IMM_LOW16 246 +#define R_SH_IMM_LOW16_PCREL 247 +#define R_SH_IMM_MEDLOW16 248 +#define R_SH_IMM_MEDLOW16_PCREL 249 /* Keep this the last entry. */ #define R_SH_NUM 256 @@ -58,11 +63,6 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR typedef struct user_fpu_struct elf_fpregset_t; /* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ( (x)->e_machine == EM_SH ) - -/* * These are used to set parameters in the core dumps. */ #define ELF_CLASS ELFCLASS32 @@ -73,6 +73,12 @@ typedef struct user_fpu_struct elf_fpreg #endif #define ELF_ARCH EM_SH +#ifdef __KERNEL__ +/* + * This is used to ensure we don't load something for the wrong architecture. + */ +#define elf_check_arch(x) ( (x)->e_machine == EM_SH ) + #define USE_ELF_CORE_DUMP #define ELF_EXEC_PAGESIZE PAGE_SIZE @@ -83,7 +89,6 @@ typedef struct user_fpu_struct elf_fpreg #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) - #define ELF_CORE_COPY_REGS(_dest,_regs) \ memcpy((char *) &_dest, (char *) _regs, \ sizeof(struct pt_regs)); @@ -101,16 +106,38 @@ typedef struct user_fpu_struct elf_fpreg For the moment, we have only optimizations for the Intel generations, but that could change... */ -#define ELF_PLATFORM (NULL) +#define ELF_PLATFORM (utsname()->machine) +#ifdef __SH5__ +#define ELF_PLAT_INIT(_r, load_addr) \ + do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \ + _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \ + _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ + _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; _r->regs[15]=0; \ + _r->regs[16]=0; _r->regs[17]=0; _r->regs[18]=0; _r->regs[19]=0; \ + _r->regs[20]=0; _r->regs[21]=0; _r->regs[22]=0; _r->regs[23]=0; \ + _r->regs[24]=0; _r->regs[25]=0; _r->regs[26]=0; _r->regs[27]=0; \ + _r->regs[28]=0; _r->regs[29]=0; _r->regs[30]=0; _r->regs[31]=0; \ + _r->regs[32]=0; _r->regs[33]=0; _r->regs[34]=0; _r->regs[35]=0; \ + _r->regs[36]=0; _r->regs[37]=0; _r->regs[38]=0; _r->regs[39]=0; \ + _r->regs[40]=0; _r->regs[41]=0; _r->regs[42]=0; _r->regs[43]=0; \ + _r->regs[44]=0; _r->regs[45]=0; _r->regs[46]=0; _r->regs[47]=0; \ + _r->regs[48]=0; _r->regs[49]=0; _r->regs[50]=0; _r->regs[51]=0; \ + _r->regs[52]=0; _r->regs[53]=0; _r->regs[54]=0; _r->regs[55]=0; \ + _r->regs[56]=0; _r->regs[57]=0; _r->regs[58]=0; _r->regs[59]=0; \ + _r->regs[60]=0; _r->regs[61]=0; _r->regs[62]=0; \ + _r->tregs[0]=0; _r->tregs[1]=0; _r->tregs[2]=0; _r->tregs[3]=0; \ + _r->tregs[4]=0; _r->tregs[5]=0; _r->tregs[6]=0; _r->tregs[7]=0; \ + _r->sr = SR_FD | SR_MMU; } while (0) +#else #define ELF_PLAT_INIT(_r, load_addr) \ do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \ _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \ _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; \ _r->sr = SR_FD; } while (0) +#endif -#ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) struct task_struct; extern int dump_task_regs (struct task_struct *, elf_gregset_t *); @@ -118,7 +145,6 @@ extern int dump_task_fpu (struct task_st #define ELF_CORE_COPY_TASK_REGS(tsk, elf_regs) dump_task_regs(tsk, elf_regs) #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs) -#endif #ifdef CONFIG_VSYSCALL /* vDSO has arch_setup_additional_pages */ @@ -133,12 +159,35 @@ extern void __kernel_vsyscall; #define VDSO_BASE ((unsigned long)current->mm->context.vdso) #define VDSO_SYM(x) (VDSO_BASE + (unsigned long)(x)) +#define VSYSCALL_AUX_ENT \ + if (vdso_enabled) \ + NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); +#else +#define VSYSCALL_AUX_ENT +#endif /* CONFIG_VSYSCALL */ + +#ifdef CONFIG_SH_FPU +#define FPU_AUX_ENT NEW_AUX_ENT(AT_FPUCW, FPSCR_INIT) +#else +#define FPU_AUX_ENT +#endif + +extern int l1i_cache_shape, l1d_cache_shape, l2_cache_shape; + /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ #define ARCH_DLINFO \ do { \ - if (vdso_enabled) \ - NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE); \ + /* Optional FPU initialization */ \ + FPU_AUX_ENT; \ + \ + /* Optional vsyscall entry */ \ + VSYSCALL_AUX_ENT; \ + \ + /* Cache desc */ \ + NEW_AUX_ENT(AT_L1I_CACHESHAPE, l1i_cache_shape); \ + NEW_AUX_ENT(AT_L1D_CACHESHAPE, l1d_cache_shape); \ + NEW_AUX_ENT(AT_L2_CACHESHAPE, l2_cache_shape); \ } while (0) -#endif /* CONFIG_VSYSCALL */ +#endif /* __KERNEL__ */ #endif /* __ASM_SH_ELF_H */ diff -puN include/asm-sh/fixmap.h~git-sh include/asm-sh/fixmap.h --- a/include/asm-sh/fixmap.h~git-sh +++ a/include/asm-sh/fixmap.h @@ -49,6 +49,7 @@ enum fixed_addresses { #define FIX_N_COLOURS 16 FIX_CMAP_BEGIN, FIX_CMAP_END = FIX_CMAP_BEGIN + FIX_N_COLOURS, + FIX_UNCACHED, #ifdef CONFIG_HIGHMEM FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1, @@ -73,7 +74,11 @@ extern void __set_fixmap(enum fixed_addr * the start of the fixmap, and leave one page empty * at the top of mem.. */ +#ifdef CONFIG_SUPERH32 #define FIXADDR_TOP (P4SEG - PAGE_SIZE) +#else +#define FIXADDR_TOP (0xff000000 - PAGE_SIZE) +#endif #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) #define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE) diff -puN include/asm-sh/flat.h~git-sh include/asm-sh/flat.h --- a/include/asm-sh/flat.h~git-sh +++ a/include/asm-sh/flat.h @@ -19,6 +19,6 @@ #define flat_get_addr_from_rp(rp, relval, flags, p) get_unaligned(rp) #define flat_put_addr_at_rp(rp, val, relval) put_unaligned(val,rp) #define flat_get_relocate_addr(rel) (rel) -#define flat_set_persistent(relval, p) 0 +#define flat_set_persistent(relval, p) ({ (void)p; 0; }) #endif /* __ASM_SH_FLAT_H */ diff -puN /dev/null include/asm-sh/fpu.h --- /dev/null +++ a/include/asm-sh/fpu.h @@ -0,0 +1,46 @@ +#ifndef __ASM_SH_FPU_H +#define __ASM_SH_FPU_H + +#define SR_FD 0x00008000 + +#ifndef __ASSEMBLY__ +#include + +#ifdef CONFIG_SH_FPU +static inline void release_fpu(struct pt_regs *regs) +{ + regs->sr |= SR_FD; +} + +static inline void grab_fpu(struct pt_regs *regs) +{ + regs->sr &= ~SR_FD; +} + +struct task_struct; + +extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); +#else +#define release_fpu(regs) do { } while (0) +#define grab_fpu(regs) do { } while (0) +#define save_fpu(tsk, regs) do { } while (0) +#endif + +extern int do_fpu_inst(unsigned short, struct pt_regs *); + +#define unlazy_fpu(tsk, regs) do { \ + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ + save_fpu(tsk, regs); \ + } \ +} while (0) + +#define clear_fpu(tsk, regs) do { \ + if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ + clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ + release_fpu(regs); \ + } \ +} while (0) + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_SH_FPU_H */ diff -puN include/asm-sh/hd64461.h~git-sh include/asm-sh/hd64461.h --- a/include/asm-sh/hd64461.h~git-sh +++ a/include/asm-sh/hd64461.h @@ -46,10 +46,10 @@ /* CPU Data Bus Control Register */ #define HD64461_SCPUCR (CONFIG_HD64461_IOBASE + 0x04) -/* Base Adress Register */ +/* Base Address Register */ #define HD64461_LCDCBAR (CONFIG_HD64461_IOBASE + 0x1000) -/* Line increment adress */ +/* Line increment address */ #define HD64461_LCDCLOR (CONFIG_HD64461_IOBASE + 0x1002) /* Controls LCD controller */ @@ -80,9 +80,9 @@ #define HD64461_LDR3 (CONFIG_HD64461_IOBASE + 0x101e) /* Palette Registers */ -#define HD64461_CPTWAR (CONFIG_HD64461_IOBASE + 0x1030) /* Color Palette Write Adress Register */ +#define HD64461_CPTWAR (CONFIG_HD64461_IOBASE + 0x1030) /* Color Palette Write Address Register */ #define HD64461_CPTWDR (CONFIG_HD64461_IOBASE + 0x1032) /* Color Palette Write Data Register */ -#define HD64461_CPTRAR (CONFIG_HD64461_IOBASE + 0x1034) /* Color Palette Read Adress Register */ +#define HD64461_CPTRAR (CONFIG_HD64461_IOBASE + 0x1034) /* Color Palette Read Address Register */ #define HD64461_CPTRDR (CONFIG_HD64461_IOBASE + 0x1036) /* Color Palette Read Data Register */ #define HD64461_GRDOR (CONFIG_HD64461_IOBASE + 0x1040) /* Display Resolution Offset Register */ @@ -97,8 +97,8 @@ #define HD64461_GRCFGR_COLORDEPTH8 0x01 /* Sets Colordepth 8 for Accelerator */ /* Line Drawing Registers */ -#define HD64461_LNSARH (CONFIG_HD64461_IOBASE + 0x1046) /* Line Start Adress Register (H) */ -#define HD64461_LNSARL (CONFIG_HD64461_IOBASE + 0x1048) /* Line Start Adress Register (L) */ +#define HD64461_LNSARH (CONFIG_HD64461_IOBASE + 0x1046) /* Line Start Address Register (H) */ +#define HD64461_LNSARL (CONFIG_HD64461_IOBASE + 0x1048) /* Line Start Address Register (L) */ #define HD64461_LNAXLR (CONFIG_HD64461_IOBASE + 0x104a) /* Axis Pixel Length Register */ #define HD64461_LNDGR (CONFIG_HD64461_IOBASE + 0x104c) /* Diagonal Register */ #define HD64461_LNAXR (CONFIG_HD64461_IOBASE + 0x104e) /* Axial Register */ @@ -106,16 +106,16 @@ #define HD64461_LNMDR (CONFIG_HD64461_IOBASE + 0x1052) /* Line Mode Register */ /* BitBLT Registers */ -#define HD64461_BBTSSARH (CONFIG_HD64461_IOBASE + 0x1054) /* Source Start Adress Register (H) */ -#define HD64461_BBTSSARL (CONFIG_HD64461_IOBASE + 0x1056) /* Source Start Adress Register (L) */ -#define HD64461_BBTDSARH (CONFIG_HD64461_IOBASE + 0x1058) /* Destination Start Adress Register (H) */ -#define HD64461_BBTDSARL (CONFIG_HD64461_IOBASE + 0x105a) /* Destination Start Adress Register (L) */ +#define HD64461_BBTSSARH (CONFIG_HD64461_IOBASE + 0x1054) /* Source Start Address Register (H) */ +#define HD64461_BBTSSARL (CONFIG_HD64461_IOBASE + 0x1056) /* Source Start Address Register (L) */ +#define HD64461_BBTDSARH (CONFIG_HD64461_IOBASE + 0x1058) /* Destination Start Address Register (H) */ +#define HD64461_BBTDSARL (CONFIG_HD64461_IOBASE + 0x105a) /* Destination Start Address Register (L) */ #define HD64461_BBTDWR (CONFIG_HD64461_IOBASE + 0x105c) /* Destination Block Width Register */ #define HD64461_BBTDHR (CONFIG_HD64461_IOBASE + 0x105e) /* Destination Block Height Register */ -#define HD64461_BBTPARH (CONFIG_HD64461_IOBASE + 0x1060) /* Pattern Start Adress Register (H) */ -#define HD64461_BBTPARL (CONFIG_HD64461_IOBASE + 0x1062) /* Pattern Start Adress Register (L) */ -#define HD64461_BBTMARH (CONFIG_HD64461_IOBASE + 0x1064) /* Mask Start Adress Register (H) */ -#define HD64461_BBTMARL (CONFIG_HD64461_IOBASE + 0x1066) /* Mask Start Adress Register (L) */ +#define HD64461_BBTPARH (CONFIG_HD64461_IOBASE + 0x1060) /* Pattern Start Address Register (H) */ +#define HD64461_BBTPARL (CONFIG_HD64461_IOBASE + 0x1062) /* Pattern Start Address Register (L) */ +#define HD64461_BBTMARH (CONFIG_HD64461_IOBASE + 0x1064) /* Mask Start Address Register (H) */ +#define HD64461_BBTMARL (CONFIG_HD64461_IOBASE + 0x1066) /* Mask Start Address Register (L) */ #define HD64461_BBTROPR (CONFIG_HD64461_IOBASE + 0x1068) /* ROP Register */ #define HD64461_BBTMDR (CONFIG_HD64461_IOBASE + 0x106a) /* BitBLT Mode Register */ diff -puN include/asm-sh/io.h~git-sh include/asm-sh/io.h --- a/include/asm-sh/io.h~git-sh +++ a/include/asm-sh/io.h @@ -191,6 +191,8 @@ __BUILD_MEMORY_STRING(w, u16) #define mmiowb() wmb() /* synco on SH-4A, otherwise a nop */ +#define IO_SPACE_LIMIT 0xffffffff + /* * This function provides a method for the generic case where a board-specific * ioport_map simply needs to return the port + some arbitrary port base. @@ -226,6 +228,11 @@ static inline unsigned int ctrl_inl(unsi return *(volatile unsigned long*)addr; } +static inline unsigned long long ctrl_inq(unsigned long addr) +{ + return *(volatile unsigned long long*)addr; +} + static inline void ctrl_outb(unsigned char b, unsigned long addr) { *(volatile unsigned char*)addr = b; @@ -241,49 +248,52 @@ static inline void ctrl_outl(unsigned in *(volatile unsigned long*)addr = b; } -static inline void ctrl_delay(void) +static inline void ctrl_outq(unsigned long long b, unsigned long addr) { - ctrl_inw(P2SEG); + *(volatile unsigned long long*)addr = b; } -#define IO_SPACE_LIMIT 0xffffffff - -#ifdef CONFIG_MMU -/* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/SuperH mapping - */ -static inline unsigned long virt_to_phys(volatile void *address) +static inline void ctrl_delay(void) { - return PHYSADDR(address); +#ifdef P2SEG + ctrl_inw(P2SEG); +#endif } -static inline void *phys_to_virt(unsigned long address) -{ - return (void *)P1SEGADDR(address); -} -#else -#define phys_to_virt(address) ((void *)(address)) +/* Quad-word real-mode I/O, don't ask.. */ +unsigned long long peek_real_address_q(unsigned long long addr); +unsigned long long poke_real_address_q(unsigned long long addr, + unsigned long long val); + +/* arch/sh/mm/ioremap_64.c */ +unsigned long onchip_remap(unsigned long addr, unsigned long size, + const char *name); +extern void onchip_unmap(unsigned long vaddr); + +#if !defined(CONFIG_MMU) #define virt_to_phys(address) ((unsigned long)(address)) +#define phys_to_virt(address) ((void *)(address)) +#else +#define virt_to_phys(address) (__pa(address)) +#define phys_to_virt(address) (__va(address)) #endif /* - * readX/writeX() are used to access memory mapped devices. On some - * architectures the memory mapped IO stuff needs to be accessed - * differently. On the x86 architecture, we just read/write the - * memory location directly. + * On 32-bit SH, we traditionally have the whole physical address space + * mapped at all times (as MIPS does), so "ioremap()" and "iounmap()" do + * not need to do anything but place the address in the proper segment. + * This is true for P1 and P2 addresses, as well as some P3 ones. + * However, most of the P3 addresses and newer cores using extended + * addressing need to map through page tables, so the ioremap() + * implementation becomes a bit more complicated. * - * On SH, we traditionally have the whole physical address space mapped - * at all times (as MIPS does), so "ioremap()" and "iounmap()" do not - * need to do anything but place the address in the proper segment. This - * is true for P1 and P2 addresses, as well as some P3 ones. However, - * most of the P3 addresses and newer cores using extended addressing - * need to map through page tables, so the ioremap() implementation - * becomes a bit more complicated. See arch/sh/mm/ioremap.c for - * additional notes on this. + * See arch/sh/mm/ioremap.c for additional notes on this. * * We cheat a bit and always return uncachable areas until we've fixed * the drivers to handle caching properly. + * + * On the SH-5 the concept of segmentation in the 1:1 PXSEG sense simply + * doesn't exist, so everything must go through page tables. */ #ifdef CONFIG_MMU void __iomem *__ioremap(unsigned long offset, unsigned long size, @@ -297,6 +307,7 @@ void __iounmap(void __iomem *addr); static inline void __iomem * __ioremap_mode(unsigned long offset, unsigned long size, unsigned long flags) { +#ifdef CONFIG_SUPERH32 unsigned long last_addr = offset + size - 1; /* @@ -311,6 +322,7 @@ __ioremap_mode(unsigned long offset, uns return (void __iomem *)P2SEGADDR(offset); } +#endif return __ioremap(offset, size, flags); } diff -puN include/asm-sh/irqflags.h~git-sh include/asm-sh/irqflags.h --- a/include/asm-sh/irqflags.h~git-sh +++ a/include/asm-sh/irqflags.h @@ -1,81 +1,11 @@ #ifndef __ASM_SH_IRQFLAGS_H #define __ASM_SH_IRQFLAGS_H -static inline void raw_local_irq_enable(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and %1, %0\n\t" -#ifdef CONFIG_CPU_HAS_SR_RB - "stc r6_bank, %1\n\t" - "or %1, %0\n\t" +#ifdef CONFIG_SUPERH32 +#include "irqflags_32.h" +#else +#include "irqflags_64.h" #endif - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x000000f0) - : "memory" - ); -} - -static inline void raw_local_irq_disable(void) -{ - unsigned long flags; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr\n\t" - : "=&z" (flags) - : /* no inputs */ - : "memory" - ); -} - -static inline void set_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "or %2, %0\n\t" - "and %3, %0\n\t" - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "r" (0x10000000), "r" (0xffffff0f) - : "memory" - ); -} - -static inline void clear_bl_bit(void) -{ - unsigned long __dummy0, __dummy1; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and %2, %0\n\t" - "ldc %0, sr\n\t" - : "=&r" (__dummy0), "=r" (__dummy1) - : "1" (~0x10000000) - : "memory" - ); -} - -static inline unsigned long __raw_local_save_flags(void) -{ - unsigned long flags; - - __asm__ __volatile__ ( - "stc sr, %0\n\t" - "and #0xf0, %0\n\t" - : "=&z" (flags) - : /* no inputs */ - : "memory" - ); - - return flags; -} #define raw_local_save_flags(flags) \ do { (flags) = __raw_local_save_flags(); } while (0) @@ -92,25 +22,6 @@ static inline int raw_irqs_disabled(void return raw_irqs_disabled_flags(flags); } -static inline unsigned long __raw_local_irq_save(void) -{ - unsigned long flags, __dummy; - - __asm__ __volatile__ ( - "stc sr, %1\n\t" - "mov %1, %0\n\t" - "or #0xf0, %0\n\t" - "ldc %0, sr\n\t" - "mov %1, %0\n\t" - "and #0xf0, %0\n\t" - : "=&z" (flags), "=&r" (__dummy) - : /* no inputs */ - : "memory" - ); - - return flags; -} - #define raw_local_irq_save(flags) \ do { (flags) = __raw_local_irq_save(); } while (0) diff -puN /dev/null include/asm-sh/irqflags_32.h --- /dev/null +++ a/include/asm-sh/irqflags_32.h @@ -0,0 +1,99 @@ +#ifndef __ASM_SH_IRQFLAGS_32_H +#define __ASM_SH_IRQFLAGS_32_H + +static inline void raw_local_irq_enable(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %1, %0\n\t" +#ifdef CONFIG_CPU_HAS_SR_RB + "stc r6_bank, %1\n\t" + "or %1, %0\n\t" +#endif + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~0x000000f0) + : "memory" + ); +} + +static inline void raw_local_irq_disable(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or #0xf0, %0\n\t" + "ldc %0, sr\n\t" + : "=&z" (flags) + : /* no inputs */ + : "memory" + ); +} + +static inline void set_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "or %2, %0\n\t" + "and %3, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "r" (0x10000000), "r" (0xffffff0f) + : "memory" + ); +} + +static inline void clear_bl_bit(void) +{ + unsigned long __dummy0, __dummy1; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and %2, %0\n\t" + "ldc %0, sr\n\t" + : "=&r" (__dummy0), "=r" (__dummy1) + : "1" (~0x10000000) + : "memory" + ); +} + +static inline unsigned long __raw_local_save_flags(void) +{ + unsigned long flags; + + __asm__ __volatile__ ( + "stc sr, %0\n\t" + "and #0xf0, %0\n\t" + : "=&z" (flags) + : /* no inputs */ + : "memory" + ); + + return flags; +} + +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long flags, __dummy; + + __asm__ __volatile__ ( + "stc sr, %1\n\t" + "mov %1, %0\n\t" + "or #0xf0, %0\n\t" + "ldc %0, sr\n\t" + "mov %1, %0\n\t" + "and #0xf0, %0\n\t" + : "=&z" (flags), "=&r" (__dummy) + : /* no inputs */ + : "memory" + ); + + return flags; +} + +#endif /* __ASM_SH_IRQFLAGS_32_H */ diff -puN /dev/null include/asm-sh/irqflags_64.h --- /dev/null +++ a/include/asm-sh/irqflags_64.h @@ -0,0 +1,85 @@ +#ifndef __ASM_SH_IRQFLAGS_64_H +#define __ASM_SH_IRQFLAGS_64_H + +#include + +#define SR_MASK_LL 0x00000000000000f0LL +#define SR_BL_LL 0x0000000010000000LL + +static inline void raw_local_irq_enable(void) +{ + unsigned long long __dummy0, __dummy1 = ~SR_MASK_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); +} + +static inline void raw_local_irq_disable(void) +{ + unsigned long long __dummy0, __dummy1 = SR_MASK_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "or %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); +} + +static inline void set_bl_bit(void) +{ + unsigned long long __dummy0, __dummy1 = SR_BL_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "or %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); + +} + +static inline void clear_bl_bit(void) +{ + unsigned long long __dummy0, __dummy1 = ~SR_BL_LL; + + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy0) + : "r" (__dummy1)); +} + +static inline unsigned long __raw_local_save_flags(void) +{ + unsigned long long __dummy = SR_MASK_LL; + unsigned long flags; + + __asm__ __volatile__ ( + "getcon " __SR ", %0\n\t" + "and %0, %1, %0" + : "=&r" (flags) + : "r" (__dummy)); + + return flags; +} + +static inline unsigned long __raw_local_irq_save(void) +{ + unsigned long long __dummy0, __dummy1 = SR_MASK_LL; + unsigned long flags; + + __asm__ __volatile__ ( + "getcon " __SR ", %1\n\t" + "or %1, r63, %0\n\t" + "or %1, %2, %1\n\t" + "putcon %1, " __SR "\n\t" + "and %0, %2, %0" + : "=&r" (flags), "=&r" (__dummy0) + : "r" (__dummy1)); + + return flags; +} + +#endif /* __ASM_SH_IRQFLAGS_64_H */ diff -puN include/asm-sh/microdev.h~git-sh include/asm-sh/microdev.h --- a/include/asm-sh/microdev.h~git-sh +++ a/include/asm-sh/microdev.h @@ -17,7 +17,7 @@ extern void microdev_print_fpga_intc_sta /* * The following are useful macros for manipulating the interrupt * controller (INTC) on the CPU-board FPGA. should be noted that there - * is an INTC on the FPGA, and a seperate INTC on the SH4-202 core - + * is an INTC on the FPGA, and a separate INTC on the SH4-202 core - * these are two different things, both of which need to be prorammed to * correctly route - unfortunately, they have the same name and * abbreviations! @@ -25,7 +25,7 @@ extern void microdev_print_fpga_intc_sta #define MICRODEV_FPGA_INTC_BASE 0xa6110000ul /* INTC base address on CPU-board FPGA */ #define MICRODEV_FPGA_INTENB_REG (MICRODEV_FPGA_INTC_BASE+0ul) /* Interrupt Enable Register on INTC on CPU-board FPGA */ #define MICRODEV_FPGA_INTDSB_REG (MICRODEV_FPGA_INTC_BASE+8ul) /* Interrupt Disable Register on INTC on CPU-board FPGA */ -#define MICRODEV_FPGA_INTC_MASK(n) (1ul<<(n)) /* Interupt mask to enable/disable INTC in CPU-board FPGA */ +#define MICRODEV_FPGA_INTC_MASK(n) (1ul<<(n)) /* Interrupt mask to enable/disable INTC in CPU-board FPGA */ #define MICRODEV_FPGA_INTPRI_REG(n) (MICRODEV_FPGA_INTC_BASE+0x10+((n)/8)*8)/* Interrupt Priority Register on INTC on CPU-board FPGA */ #define MICRODEV_FPGA_INTPRI_LEVEL(n,x) ((x)<<(((n)%8)*4)) /* MICRODEV_FPGA_INTPRI_LEVEL(int_number, int_level) */ #define MICRODEV_FPGA_INTPRI_MASK(n) (MICRODEV_FPGA_INTPRI_LEVEL((n),0xful)) /* Interrupt Priority Mask on INTC on CPU-board FPGA */ diff -puN include/asm-sh/mmu_context.h~git-sh include/asm-sh/mmu_context.h --- a/include/asm-sh/mmu_context.h~git-sh +++ a/include/asm-sh/mmu_context.h @@ -1,13 +1,13 @@ /* * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2003 - 2006 Paul Mundt + * Copyright (C) 2003 - 2007 Paul Mundt * * ASID handling idea taken from MIPS implementation. */ #ifndef __ASM_SH_MMU_CONTEXT_H #define __ASM_SH_MMU_CONTEXT_H -#ifdef __KERNEL__ +#ifdef __KERNEL__ #include #include #include @@ -19,7 +19,6 @@ * (a) TLB cache version (or round, cycle whatever expression you like) * (b) ASID (Address Space IDentifier) */ - #define MMU_CONTEXT_ASID_MASK 0x000000ff #define MMU_CONTEXT_VERSION_MASK 0xffffff00 #define MMU_CONTEXT_FIRST_VERSION 0x00000100 @@ -28,10 +27,11 @@ /* ASID is 8-bit value, so it can't be 0x100 */ #define MMU_NO_ASID 0x100 -#define cpu_context(cpu, mm) ((mm)->context.id[cpu]) -#define cpu_asid(cpu, mm) (cpu_context((cpu), (mm)) & \ - MMU_CONTEXT_ASID_MASK) #define asid_cache(cpu) (cpu_data[cpu].asid_cache) +#define cpu_context(cpu, mm) ((mm)->context.id[cpu]) + +#define cpu_asid(cpu, mm) \ + (cpu_context((cpu), (mm)) & MMU_CONTEXT_ASID_MASK) /* * Virtual Page Number mask @@ -39,6 +39,12 @@ #define MMU_VPN_MASK 0xfffff000 #ifdef CONFIG_MMU +#if defined(CONFIG_SUPERH32) +#include "mmu_context_32.h" +#else +#include "mmu_context_64.h" +#endif + /* * Get MMU context if needed. */ @@ -59,6 +65,14 @@ static inline void get_mmu_context(struc */ flush_tlb_all(); +#ifdef CONFIG_SUPERH64 + /* + * The SH-5 cache uses the ASIDs, requiring both the I and D + * cache to be flushed when the ASID is exhausted. Weak. + */ + flush_cache_all(); +#endif + /* * Fix version; Note that we avoid version #0 * to distingush NO_CONTEXT. @@ -86,39 +100,6 @@ static inline int init_new_context(struc } /* - * Destroy context related info for an mm_struct that is about - * to be put to rest. - */ -static inline void destroy_context(struct mm_struct *mm) -{ - /* Do nothing */ -} - -static inline void set_asid(unsigned long asid) -{ - unsigned long __dummy; - - __asm__ __volatile__ ("mov.l %2, %0\n\t" - "and %3, %0\n\t" - "or %1, %0\n\t" - "mov.l %0, %2" - : "=&r" (__dummy) - : "r" (asid), "m" (__m(MMU_PTEH)), - "r" (0xffffff00)); -} - -static inline unsigned long get_asid(void) -{ - unsigned long asid; - - __asm__ __volatile__ ("mov.l %1, %0" - : "=r" (asid) - : "m" (__m(MMU_PTEH))); - asid &= MMU_CONTEXT_ASID_MASK; - return asid; -} - -/* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. */ @@ -128,17 +109,6 @@ static inline void activate_context(stru set_asid(cpu_asid(cpu, mm)); } -/* MMU_TTB is used for optimizing the fault handling. */ -static inline void set_TTB(pgd_t *pgd) -{ - ctrl_outl((unsigned long)pgd, MMU_TTB); -} - -static inline pgd_t *get_TTB(void) -{ - return (pgd_t *)ctrl_inl(MMU_TTB); -} - static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) @@ -153,17 +123,7 @@ static inline void switch_mm(struct mm_s if (!cpu_test_and_set(cpu, next->cpu_vm_mask)) activate_context(next, cpu); } - -#define deactivate_mm(tsk,mm) do { } while (0) - -#define activate_mm(prev, next) \ - switch_mm((prev),(next),NULL) - -static inline void -enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} -#else /* !CONFIG_MMU */ +#else #define get_mmu_context(mm) do { } while (0) #define init_new_context(tsk,mm) (0) #define destroy_context(mm) do { } while (0) @@ -173,10 +133,11 @@ enter_lazy_tlb(struct mm_struct *mm, str #define get_TTB() (0) #define activate_context(mm,cpu) do { } while (0) #define switch_mm(prev,next,tsk) do { } while (0) +#endif /* CONFIG_MMU */ + +#define activate_mm(prev, next) switch_mm((prev),(next),NULL) #define deactivate_mm(tsk,mm) do { } while (0) -#define activate_mm(prev,next) do { } while (0) #define enter_lazy_tlb(mm,tsk) do { } while (0) -#endif /* CONFIG_MMU */ #if defined(CONFIG_CPU_SH3) || defined(CONFIG_CPU_SH4) /* diff -puN /dev/null include/asm-sh/mmu_context_32.h --- /dev/null +++ a/include/asm-sh/mmu_context_32.h @@ -0,0 +1,47 @@ +#ifndef __ASM_SH_MMU_CONTEXT_32_H +#define __ASM_SH_MMU_CONTEXT_32_H + +/* + * Destroy context related info for an mm_struct that is about + * to be put to rest. + */ +static inline void destroy_context(struct mm_struct *mm) +{ + /* Do nothing */ +} + +static inline void set_asid(unsigned long asid) +{ + unsigned long __dummy; + + __asm__ __volatile__ ("mov.l %2, %0\n\t" + "and %3, %0\n\t" + "or %1, %0\n\t" + "mov.l %0, %2" + : "=&r" (__dummy) + : "r" (asid), "m" (__m(MMU_PTEH)), + "r" (0xffffff00)); +} + +static inline unsigned long get_asid(void) +{ + unsigned long asid; + + __asm__ __volatile__ ("mov.l %1, %0" + : "=r" (asid) + : "m" (__m(MMU_PTEH))); + asid &= MMU_CONTEXT_ASID_MASK; + return asid; +} + +/* MMU_TTB is used for optimizing the fault handling. */ +static inline void set_TTB(pgd_t *pgd) +{ + ctrl_outl((unsigned long)pgd, MMU_TTB); +} + +static inline pgd_t *get_TTB(void) +{ + return (pgd_t *)ctrl_inl(MMU_TTB); +} +#endif /* __ASM_SH_MMU_CONTEXT_32_H */ diff -puN /dev/null include/asm-sh/mmu_context_64.h --- /dev/null +++ a/include/asm-sh/mmu_context_64.h @@ -0,0 +1,75 @@ +#ifndef __ASM_SH_MMU_CONTEXT_64_H +#define __ASM_SH_MMU_CONTEXT_64_H + +/* + * sh64-specific mmu_context interface. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include + +#define SR_ASID_MASK 0xffffffffff00ffffULL +#define SR_ASID_SHIFT 16 + +/* + * Destroy context related info for an mm_struct that is about + * to be put to rest. + */ +static inline void destroy_context(struct mm_struct *mm) +{ + /* Well, at least free TLB entries */ + flush_tlb_mm(mm); +} + +static inline unsigned long get_asid(void) +{ + unsigned long long sr; + + asm volatile ("getcon " __SR ", %0\n\t" + : "=r" (sr)); + + sr = (sr >> SR_ASID_SHIFT) & MMU_CONTEXT_ASID_MASK; + return (unsigned long) sr; +} + +/* Set ASID into SR */ +static inline void set_asid(unsigned long asid) +{ + unsigned long long sr, pc; + + asm volatile ("getcon " __SR ", %0" : "=r" (sr)); + + sr = (sr & SR_ASID_MASK) | (asid << SR_ASID_SHIFT); + + /* + * It is possible that this function may be inlined and so to avoid + * the assembler reporting duplicate symbols we make use of the + * gas trick of generating symbols using numerics and forward + * reference. + */ + asm volatile ("movi 1, %1\n\t" + "shlli %1, 28, %1\n\t" + "or %0, %1, %1\n\t" + "putcon %1, " __SR "\n\t" + "putcon %0, " __SSR "\n\t" + "movi 1f, %1\n\t" + "ori %1, 1 , %1\n\t" + "putcon %1, " __SPC "\n\t" + "rte\n" + "1:\n\t" + : "=r" (sr), "=r" (pc) : "0" (sr)); +} + +/* No spare register to twiddle, so use a software cache */ +extern pgd_t *mmu_pdtp_cache; + +#define set_TTB(pgd) (mmu_pdtp_cache = (pgd)) +#define get_TTB() (mmu_pdtp_cache) + +#endif /* __ASM_SH_MMU_CONTEXT_64_H */ diff -puN include/asm-sh/module.h~git-sh include/asm-sh/module.h --- a/include/asm-sh/module.h~git-sh +++ a/include/asm-sh/module.h @@ -20,6 +20,8 @@ struct mod_arch_specific { # define MODULE_PROC_FAMILY "SH3LE " # elif defined CONFIG_CPU_SH4 # define MODULE_PROC_FAMILY "SH4LE " +# elif defined CONFIG_CPU_SH5 +# define MODULE_PROC_FAMILY "SH5LE " # else # error unknown processor family # endif @@ -30,6 +32,8 @@ struct mod_arch_specific { # define MODULE_PROC_FAMILY "SH3BE " # elif defined CONFIG_CPU_SH4 # define MODULE_PROC_FAMILY "SH4BE " +# elif defined CONFIG_CPU_SH5 +# define MODULE_PROC_FAMILY "SH5BE " # else # error unknown processor family # endif diff -puN include/asm-sh/page.h~git-sh include/asm-sh/page.h --- a/include/asm-sh/page.h~git-sh +++ a/include/asm-sh/page.h @@ -5,13 +5,7 @@ * Copyright (C) 1999 Niibe Yutaka */ -/* - [ P0/U0 (virtual) ] 0x00000000 <------ User space - [ P1 (fixed) cached ] 0x80000000 <------ Kernel space - [ P2 (fixed) non-cachable] 0xA0000000 <------ Physical access - [ P3 (virtual) cached] 0xC0000000 <------ vmalloced area - [ P4 control ] 0xE0000000 - */ +#include #ifdef __KERNEL__ @@ -26,15 +20,13 @@ # error "Bogus kernel page size?" #endif -#ifdef __ASSEMBLY__ -#define PAGE_SIZE (1 << PAGE_SHIFT) -#else -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#endif - +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) #define PTE_MASK PAGE_MASK +/* to align the pointer to the (next) page boundary */ +#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) + #if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) #define HPAGE_SHIFT 16 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) @@ -45,6 +37,8 @@ #define HPAGE_SHIFT 22 #elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) #define HPAGE_SHIFT 26 +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512MB) +#define HPAGE_SHIFT 29 #endif #ifdef CONFIG_HUGETLB_PAGE @@ -55,20 +49,12 @@ #ifndef __ASSEMBLY__ -extern void (*clear_page)(void *to); -extern void (*copy_page)(void *to, void *from); - extern unsigned long shm_align_mask; extern unsigned long max_low_pfn, min_low_pfn; extern unsigned long memory_start, memory_end; -#ifdef CONFIG_MMU -extern void clear_page_slow(void *to); -extern void copy_page_slow(void *to, void *from); -#else -extern void clear_page_nommu(void *to); -extern void copy_page_nommu(void *to, void *from); -#endif +extern void clear_page(void *to); +extern void copy_page(void *to, void *from); #if !defined(CONFIG_CACHE_OFF) && defined(CONFIG_MMU) && \ (defined(CONFIG_CPU_SH4) || defined(CONFIG_SH7705_CACHE_32KB)) @@ -96,12 +82,18 @@ typedef struct { unsigned long long pgd; ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) #define __pte(x) \ ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) -#else +#elif defined(CONFIG_SUPERH32) typedef struct { unsigned long pte_low; } pte_t; typedef struct { unsigned long pgprot; } pgprot_t; typedef struct { unsigned long pgd; } pgd_t; #define pte_val(x) ((x).pte_low) -#define __pte(x) ((pte_t) { (x) } ) +#define __pte(x) ((pte_t) { (x) } ) +#else +typedef struct { unsigned long long pte_low; } pte_t; +typedef struct { unsigned long pgprot; } pgprot_t; +typedef struct { unsigned long pgd; } pgd_t; +#define pte_val(x) ((x).pte_low) +#define __pte(x) ((pte_t) { (x) } ) #endif #define pgd_val(x) ((x).pgd) @@ -112,28 +104,44 @@ typedef struct { unsigned long pgd; } pg #endif /* !__ASSEMBLY__ */ -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - /* - * IF YOU CHANGE THIS, PLEASE ALSO CHANGE - * - * arch/sh/kernel/vmlinux.lds.S - * - * which has the same constant encoded.. + * __MEMORY_START and SIZE are the physical addresses and size of RAM. */ - #define __MEMORY_START CONFIG_MEMORY_START #define __MEMORY_SIZE CONFIG_MEMORY_SIZE +/* + * PAGE_OFFSET is the virtual address of the start of kernel address + * space. + */ #define PAGE_OFFSET CONFIG_PAGE_OFFSET -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) +/* + * Virtual to physical RAM address translation. + * + * In 29 bit mode, the physical offset of RAM from address 0 is visible in + * the kernel virtual address space, and thus we don't have to take + * this into account when translating. However in 32 bit mode this offset + * is not visible (it is part of the PMB mapping) and so needs to be + * added or subtracted as required. + */ +#ifdef CONFIG_32BIT +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET+__MEMORY_START) +#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET-__MEMORY_START)) +#else +#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) +#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) +#endif + +#define pfn_to_kaddr(pfn) __va((pfn) << PAGE_SHIFT) #define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT) -/* PFN start number, because of __MEMORY_START */ +/* + * PFN = physical frame number (ie PFN 0 == physical address 0) + * PFN_START is the PFN of the first page of RAM. By defining this we + * don't have struct page entries for the portion of address space + * between physical address 0 and the start of RAM. + */ #define PFN_START (__MEMORY_START >> PAGE_SHIFT) #define ARCH_PFN_OFFSET (PFN_START) #define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) @@ -154,11 +162,21 @@ typedef struct { unsigned long pgd; } pg #endif /* - * Slub defaults to 8-byte alignment, we're only interested in 4. - * Slab defaults to BYTES_PER_WORD, which ends up being the same anyways. + * Some drivers need to perform DMA into kmalloc'ed buffers + * and so we have to increase the kmalloc minalign for this. */ -#define ARCH_KMALLOC_MINALIGN 4 -#define ARCH_SLAB_MINALIGN 4 +#define ARCH_KMALLOC_MINALIGN L1_CACHE_BYTES + +#ifdef CONFIG_SUPERH64 +/* + * While BYTES_PER_WORD == 4 on the current sh64 ABI, GCC will still + * happily generate {ld/st}.q pairs, requiring us to have 8-byte + * alignment to avoid traps. The kmalloc alignment is gauranteed by + * virtue of L1_CACHE_BYTES, requiring this to only be special cased + * for slab caches. + */ +#define ARCH_SLAB_MINALIGN 8 +#endif #endif /* __KERNEL__ */ #endif /* __ASM_SH_PAGE_H */ diff -puN include/asm-sh/param.h~git-sh include/asm-sh/param.h --- a/include/asm-sh/param.h~git-sh +++ a/include/asm-sh/param.h @@ -2,11 +2,7 @@ #define __ASM_SH_PARAM_H #ifdef __KERNEL__ -# ifdef CONFIG_SH_WDT -# define HZ 1000 /* Needed for high-res WOVF */ -# else -# define HZ CONFIG_HZ -# endif +# define HZ CONFIG_HZ # define USER_HZ 100 /* User interfaces are in "ticks" */ # define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ #endif diff -puN include/asm-sh/pci.h~git-sh include/asm-sh/pci.h --- a/include/asm-sh/pci.h~git-sh +++ a/include/asm-sh/pci.h @@ -38,9 +38,12 @@ extern struct pci_channel board_pci_chan #if defined(CONFIG_CPU_SUBTYPE_SH7780) || defined(CONFIG_CPU_SUBTYPE_SH7785) #define PCI_IO_AREA 0xFE400000 #define PCI_IO_SIZE 0x00400000 +#elif defined(CONFIG_CPU_SH5) +extern unsigned long PCI_IO_AREA; +#define PCI_IO_SIZE 0x00010000 #else #define PCI_IO_AREA 0xFE240000 -#define PCI_IO_SIZE 0X00040000 +#define PCI_IO_SIZE 0x00040000 #endif #define PCI_MEM_SIZE 0x01000000 diff -puN include/asm-sh/pgtable.h~git-sh include/asm-sh/pgtable.h --- a/include/asm-sh/pgtable.h~git-sh +++ a/include/asm-sh/pgtable.h @@ -3,7 +3,7 @@ * use the SuperH page table tree. * * Copyright (C) 1999 Niibe Yutaka - * Copyright (C) 2002 - 2005 Paul Mundt + * Copyright (C) 2002 - 2007 Paul Mundt * * This file is subject to the terms and conditions of the GNU General * Public License. See the file "COPYING" in the main directory of this @@ -29,10 +29,27 @@ extern unsigned long empty_zero_page[PAG #endif /* !__ASSEMBLY__ */ /* + * Effective and physical address definitions, to aid with sign + * extension. + */ +#define NEFF 32 +#define NEFF_SIGN (1LL << (NEFF - 1)) +#define NEFF_MASK (-1LL << NEFF) + +#ifdef CONFIG_29BIT +#define NPHYS 29 +#else +#define NPHYS 32 +#endif + +#define NPHYS_SIGN (1LL << (NPHYS - 1)) +#define NPHYS_MASK (-1LL << NPHYS) + +/* * traditional two-level paging structure */ /* PTE bits */ -#ifdef CONFIG_X2TLB +#if defined(CONFIG_X2TLB) || defined(CONFIG_SUPERH64) # define PTE_MAGNITUDE 3 /* 64-bit PTEs on extended mode SH-X2 TLB */ #else # define PTE_MAGNITUDE 2 /* 32-bit PTEs */ @@ -52,284 +69,28 @@ extern unsigned long empty_zero_page[PAG #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE) #define FIRST_USER_ADDRESS 0 -#define PTE_PHYS_MASK (0x20000000 - PAGE_SIZE) - -#define VMALLOC_START (P3SEG) -#define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) - -/* - * Linux PTEL encoding. - * - * Hardware and software bit definitions for the PTEL value (see below for - * notes on SH-X2 MMUs and 64-bit PTEs): - * - * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4). - * - * - Bit 1 is the SH-bit, but is unused on SH-3 due to an MMU bug (the - * hardware PTEL value can't have the SH-bit set when MMUCR.IX is set, - * which is the default in cpu-sh3/mmu_context.h:MMU_CONTROL_INIT). - * - * In order to keep this relatively clean, do not use these for defining - * SH-3 specific flags until all of the other unused bits have been - * exhausted. - * - * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE. - * - * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages. - * Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused. - * - * - Bits 31, 30, and 29 remain unused by everyone and can be used for future - * software flags, although care must be taken to update _PAGE_CLEAR_FLAGS. - * - * XXX: Leave the _PAGE_FILE and _PAGE_WT overhaul for a rainy day. - * - * SH-X2 MMUs and extended PTEs - * - * SH-X2 supports an extended mode TLB with split data arrays due to the - * number of bits needed for PR and SZ (now EPR and ESZ) encodings. The PR and - * SZ bit placeholders still exist in data array 1, but are implemented as - * reserved bits, with the real logic existing in data array 2. - * - * The downside to this is that we can no longer fit everything in to a 32-bit - * PTE encoding, so a 64-bit pte_t is necessary for these parts. On the plus - * side, this gives us quite a few spare bits to play with for future usage. - */ -/* Legacy and compat mode bits */ -#define _PAGE_WT 0x001 /* WT-bit on SH-4, 0 on SH-3 */ -#define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */ -#define _PAGE_DIRTY 0x004 /* D-bit : page changed */ -#define _PAGE_CACHABLE 0x008 /* C-bit : cachable */ -#define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ -#define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ -#define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/ -#define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ -#define _PAGE_PRESENT 0x100 /* V-bit : page is valid */ -#define _PAGE_PROTNONE 0x200 /* software: if not present */ -#define _PAGE_ACCESSED 0x400 /* software: page referenced */ -#define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ - -#define _PAGE_SZ_MASK (_PAGE_SZ0 | _PAGE_SZ1) -#define _PAGE_PR_MASK (_PAGE_RW | _PAGE_USER) - -/* Extended mode bits */ -#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */ -#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */ -#define _PAGE_EXT_ESZ2 0x0040 /* ESZ2-bit: Size of page */ -#define _PAGE_EXT_ESZ3 0x0080 /* ESZ3-bit: Size of page */ - -#define _PAGE_EXT_USER_EXEC 0x0100 /* EPR0-bit: User space executable */ -#define _PAGE_EXT_USER_WRITE 0x0200 /* EPR1-bit: User space writable */ -#define _PAGE_EXT_USER_READ 0x0400 /* EPR2-bit: User space readable */ - -#define _PAGE_EXT_KERN_EXEC 0x0800 /* EPR3-bit: Kernel space executable */ -#define _PAGE_EXT_KERN_WRITE 0x1000 /* EPR4-bit: Kernel space writable */ -#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */ - -/* Wrapper for extended mode pgprot twiddling */ -#define _PAGE_EXT(x) ((unsigned long long)(x) << 32) - -/* software: moves to PTEA.TC (Timing Control) */ -#define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ -#define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ - -/* software: moves to PTEA.SA[2:0] (Space Attributes) */ -#define _PAGE_PCC_IODYN 0x00000001 /* IO space, dynamically sized bus */ -#define _PAGE_PCC_IO8 0x20000000 /* IO space, 8 bit bus */ -#define _PAGE_PCC_IO16 0x20000001 /* IO space, 16 bit bus */ -#define _PAGE_PCC_COM8 0x40000000 /* Common Memory space, 8 bit bus */ -#define _PAGE_PCC_COM16 0x40000001 /* Common Memory space, 16 bit bus */ -#define _PAGE_PCC_ATR8 0x60000000 /* Attribute Memory space, 8 bit bus */ -#define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */ - -/* Mask which drops unused bits from the PTEL value */ -#if defined(CONFIG_CPU_SH3) -#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED| \ - _PAGE_FILE | _PAGE_SZ1 | \ - _PAGE_HW_SHARED) -#elif defined(CONFIG_X2TLB) -/* Get rid of the legacy PR/SZ bits when using extended mode */ -#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | \ - _PAGE_FILE | _PAGE_PR_MASK | _PAGE_SZ_MASK) +#ifdef CONFIG_32BIT +#define PHYS_ADDR_MASK 0xffffffff #else -#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE) +#define PHYS_ADDR_MASK 0x1fffffff #endif -#define _PAGE_FLAGS_HARDWARE_MASK (0x1fffffff & ~(_PAGE_CLEAR_FLAGS)) +#define PTE_PHYS_MASK (PHYS_ADDR_MASK & PAGE_MASK) -/* Hardware flags, page size encoding */ -#if defined(CONFIG_X2TLB) -# if defined(CONFIG_PAGE_SIZE_4KB) -# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ0) -# elif defined(CONFIG_PAGE_SIZE_8KB) -# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ1) -# elif defined(CONFIG_PAGE_SIZE_64KB) -# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ2) -# endif +#ifdef CONFIG_SUPERH32 +#define VMALLOC_START (P3SEG) #else -# if defined(CONFIG_PAGE_SIZE_4KB) -# define _PAGE_FLAGS_HARD _PAGE_SZ0 -# elif defined(CONFIG_PAGE_SIZE_64KB) -# define _PAGE_FLAGS_HARD _PAGE_SZ1 -# endif +#define VMALLOC_START (0xf0000000) #endif +#define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) -#if defined(CONFIG_X2TLB) -# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2) -# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) -# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ2) -# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ1 | _PAGE_EXT_ESZ2) -# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) -# define _PAGE_SZHUGE (_PAGE_EXT_ESZ3) -# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) -# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3) -# endif +#if defined(CONFIG_SUPERH32) +#include #else -# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -# define _PAGE_SZHUGE (_PAGE_SZ1) -# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -# define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) -# endif +#include #endif /* - * Stub out _PAGE_SZHUGE if we don't have a good definition for it, - * to make pte_mkhuge() happy. - */ -#ifndef _PAGE_SZHUGE -# define _PAGE_SZHUGE (_PAGE_FLAGS_HARD) -#endif - -#define _PAGE_CHG_MASK \ - (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) - -#ifndef __ASSEMBLY__ - -#if defined(CONFIG_X2TLB) /* SH-X2 TLB */ -#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD) - -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_USER_READ | \ - _PAGE_EXT_USER_WRITE)) - -#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_EXEC | \ - _PAGE_EXT_KERN_READ | \ - _PAGE_EXT_USER_EXEC | \ - _PAGE_EXT_USER_READ)) - -#define PAGE_COPY PAGE_EXECREAD - -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_USER_READ)) - -#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_USER_WRITE)) - -#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ - _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_EXEC | \ - _PAGE_EXT_USER_WRITE | \ - _PAGE_EXT_USER_READ | \ - _PAGE_EXT_USER_EXEC)) - -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ - _PAGE_DIRTY | _PAGE_ACCESSED | \ - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_KERN_EXEC)) - -#define PAGE_KERNEL_NOCACHE \ - __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ - _PAGE_ACCESSED | _PAGE_HW_SHARED | \ - _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_KERN_EXEC)) - -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ - _PAGE_DIRTY | _PAGE_ACCESSED | \ - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_EXEC)) - -#define PAGE_KERNEL_PCC(slot, type) \ - __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ - _PAGE_EXT(_PAGE_EXT_KERN_READ | \ - _PAGE_EXT_KERN_WRITE | \ - _PAGE_EXT_KERN_EXEC) \ - (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ - (type)) - -#elif defined(CONFIG_MMU) /* SH-X TLB */ -#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD) - -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ - _PAGE_CACHABLE | _PAGE_ACCESSED | \ - _PAGE_FLAGS_HARD) - -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD) - -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD) - -#define PAGE_EXECREAD PAGE_READONLY -#define PAGE_RWX PAGE_SHARED -#define PAGE_WRITEONLY PAGE_SHARED - -#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | \ - _PAGE_DIRTY | _PAGE_ACCESSED | \ - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) - -#define PAGE_KERNEL_NOCACHE \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ - _PAGE_ACCESSED | _PAGE_HW_SHARED | \ - _PAGE_FLAGS_HARD) - -#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ - _PAGE_DIRTY | _PAGE_ACCESSED | \ - _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) - -#define PAGE_KERNEL_PCC(slot, type) \ - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ - _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ - (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ - (type)) -#else /* no mmu */ -#define PAGE_NONE __pgprot(0) -#define PAGE_SHARED __pgprot(0) -#define PAGE_COPY __pgprot(0) -#define PAGE_EXECREAD __pgprot(0) -#define PAGE_RWX __pgprot(0) -#define PAGE_READONLY __pgprot(0) -#define PAGE_WRITEONLY __pgprot(0) -#define PAGE_KERNEL __pgprot(0) -#define PAGE_KERNEL_NOCACHE __pgprot(0) -#define PAGE_KERNEL_RO __pgprot(0) - -#define PAGE_KERNEL_PCC(slot, type) \ - __pgprot(0) -#endif - -#endif /* __ASSEMBLY__ */ - -/* * SH-X and lower (legacy) SuperH parts (SH-3, SH-4, some SH-4A) can't do page * protection for execute, and considers it the same as a read. Also, write * permission implies read permission. This is the closest we can get.. @@ -357,208 +118,6 @@ extern unsigned long empty_zero_page[PAG #define __S110 PAGE_RWX #define __S111 PAGE_RWX -#ifndef __ASSEMBLY__ - -/* - * Certain architectures need to do special things when PTEs - * within a page table are directly modified. Thus, the following - * hook is made available. - */ -#ifdef CONFIG_X2TLB -static inline void set_pte(pte_t *ptep, pte_t pte) -{ - ptep->pte_high = pte.pte_high; - smp_wmb(); - ptep->pte_low = pte.pte_low; -} -#else -#define set_pte(pteptr, pteval) (*(pteptr) = pteval) -#endif - -#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) - -/* - * (pmds are folded into pgds so this doesn't get actually called, - * but the define is needed for a generic inline function.) - */ -#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) - -#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) - -#define pfn_pte(pfn, prot) \ - __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) -#define pfn_pmd(pfn, prot) \ - __pmd(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) - -#define pte_none(x) (!pte_val(x)) -#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE)) - -#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)) -#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) -#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) - -#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) -#define pte_page(x) pfn_to_page(pte_pfn(x)) - -/* - * The following only work if pte_present() is true. - * Undefined behaviour if not.. - */ -#define pte_not_present(pte) (!((pte).pte_low & _PAGE_PRESENT)) -#define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY) -#define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED) -#define pte_file(pte) ((pte).pte_low & _PAGE_FILE) - -#ifdef CONFIG_X2TLB -#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) -#else -#define pte_write(pte) ((pte).pte_low & _PAGE_RW) -#endif - -#define PTE_BIT_FUNC(h,fn,op) \ -static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; } - -#ifdef CONFIG_X2TLB -/* - * We cheat a bit in the SH-X2 TLB case. As the permission bits are - * individually toggled (and user permissions are entirely decoupled from - * kernel permissions), we attempt to couple them a bit more sanely here. - */ -PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE); -PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE); -PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE); -#else -PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW); -PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW); -PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE); -#endif - -PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY); -PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY); -PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED); -PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED); - -/* - * Macro and implementation to make a page protection as uncachable. - */ -#define pgprot_writecombine(prot) \ - __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) - -#define pgprot_noncached pgprot_writecombine - -/* - * Conversion functions: convert a page and protection to a page entry, - * and a page entry and page directory to the page they refer to. - * - * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) - */ -#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) - -static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ - pte.pte_low &= _PAGE_CHG_MASK; - pte.pte_low |= pgprot_val(newprot); - -#ifdef CONFIG_X2TLB - pte.pte_high |= pgprot_val(newprot) >> 32; -#endif - - return pte; -} - -#define pmd_page_vaddr(pmd) ((unsigned long)pmd_val(pmd)) -#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) - -/* to find an entry in a page-table-directory. */ -#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) - -/* to find an entry in a kernel page-table-directory */ -#define pgd_offset_k(address) pgd_offset(&init_mm, address) - -/* Find an entry in the third-level page table.. */ -#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)) -#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) -#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) - -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) - -#ifdef CONFIG_X2TLB -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \ - &(e), (e).pte_high, (e).pte_low) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %016llx.\n", __FILE__, __LINE__, pgd_val(e)) -#else -#define pte_ERROR(e) \ - printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) -#define pgd_ERROR(e) \ - printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) -#endif - -struct vm_area_struct; -extern void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte); - -/* - * Encode and de-code a swap entry - * - * Constraints: - * _PAGE_FILE at bit 0 - * _PAGE_PRESENT at bit 8 - * _PAGE_PROTNONE at bit 9 - * - * For the normal case, we encode the swap type into bits 0:7 and the - * swap offset into bits 10:30. For the 64-bit PTE case, we keep the - * preserved bits in the low 32-bits and use the upper 32 as the swap - * offset (along with a 5-bit type), following the same approach as x86 - * PAE. This keeps the logic quite simple, and allows for a full 32 - * PTE_FILE_MAX_BITS, as opposed to the 29-bits we're constrained with - * in the pte_low case. - * - * As is evident by the Alpha code, if we ever get a 64-bit unsigned - * long (swp_entry_t) to match up with the 64-bit PTEs, this all becomes - * much cleaner.. - * - * NOTE: We should set ZEROs at the position of _PAGE_PRESENT - * and _PAGE_PROTNONE bits - */ -#ifdef CONFIG_X2TLB -#define __swp_type(x) ((x).val & 0x1f) -#define __swp_offset(x) ((x).val >> 5) -#define __swp_entry(type, offset) ((swp_entry_t){ (type) | (offset) << 5}) -#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) -#define __swp_entry_to_pte(x) ((pte_t){ 0, (x).val }) - -/* - * Encode and decode a nonlinear file mapping entry - */ -#define pte_to_pgoff(pte) ((pte).pte_high) -#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) }) - -#define PTE_FILE_MAX_BITS 32 -#else -#define __swp_type(x) ((x).val & 0xff) -#define __swp_offset(x) ((x).val >> 10) -#define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) <<10}) - -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 1 }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 1 }) - -/* - * Encode and decode a nonlinear file mapping entry - */ -#define PTE_FILE_MAX_BITS 29 -#define pte_to_pgoff(pte) (pte_val(pte) >> 1) -#define pgoff_to_pte(off) ((pte_t) { ((off) << 1) | _PAGE_FILE }) -#endif - typedef pte_t *pte_addr_t; #define kern_addr_valid(addr) (1) @@ -566,27 +125,28 @@ typedef pte_t *pte_addr_t; #define io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot) -struct mm_struct; +#define pte_pfn(x) ((unsigned long)(((x).pte_low >> PAGE_SHIFT))) /* * No page table caches to initialise */ #define pgtable_cache_init() do { } while (0) -#ifndef CONFIG_MMU -extern unsigned int kobjsize(const void *objp); -#endif /* !CONFIG_MMU */ - #if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \ defined(CONFIG_SH7705_CACHE_32KB)) +struct mm_struct; #define __HAVE_ARCH_PTEP_GET_AND_CLEAR -extern pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); +pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep); #endif +struct vm_area_struct; +extern void update_mmu_cache(struct vm_area_struct * vma, + unsigned long address, pte_t pte); extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init(void); +extern void page_table_range_init(unsigned long start, unsigned long end, + pgd_t *pgd); #include -#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_SH_PAGE_H */ +#endif /* __ASM_SH_PGTABLE_H */ diff -puN /dev/null include/asm-sh/pgtable_32.h --- /dev/null +++ a/include/asm-sh/pgtable_32.h @@ -0,0 +1,474 @@ +#ifndef __ASM_SH_PGTABLE_32_H +#define __ASM_SH_PGTABLE_32_H + +/* + * Linux PTEL encoding. + * + * Hardware and software bit definitions for the PTEL value (see below for + * notes on SH-X2 MMUs and 64-bit PTEs): + * + * - Bits 0 and 7 are reserved on SH-3 (_PAGE_WT and _PAGE_SZ1 on SH-4). + * + * - Bit 1 is the SH-bit, but is unused on SH-3 due to an MMU bug (the + * hardware PTEL value can't have the SH-bit set when MMUCR.IX is set, + * which is the default in cpu-sh3/mmu_context.h:MMU_CONTROL_INIT). + * + * In order to keep this relatively clean, do not use these for defining + * SH-3 specific flags until all of the other unused bits have been + * exhausted. + * + * - Bit 9 is reserved by everyone and used by _PAGE_PROTNONE. + * + * - Bits 10 and 11 are low bits of the PPN that are reserved on >= 4K pages. + * Bit 10 is used for _PAGE_ACCESSED, bit 11 remains unused. + * + * - On 29 bit platforms, bits 31 to 29 are used for the space attributes + * and timing control which (together with bit 0) are moved into the + * old-style PTEA on the parts that support it. + * + * XXX: Leave the _PAGE_FILE and _PAGE_WT overhaul for a rainy day. + * + * SH-X2 MMUs and extended PTEs + * + * SH-X2 supports an extended mode TLB with split data arrays due to the + * number of bits needed for PR and SZ (now EPR and ESZ) encodings. The PR and + * SZ bit placeholders still exist in data array 1, but are implemented as + * reserved bits, with the real logic existing in data array 2. + * + * The downside to this is that we can no longer fit everything in to a 32-bit + * PTE encoding, so a 64-bit pte_t is necessary for these parts. On the plus + * side, this gives us quite a few spare bits to play with for future usage. + */ +/* Legacy and compat mode bits */ +#define _PAGE_WT 0x001 /* WT-bit on SH-4, 0 on SH-3 */ +#define _PAGE_HW_SHARED 0x002 /* SH-bit : shared among processes */ +#define _PAGE_DIRTY 0x004 /* D-bit : page changed */ +#define _PAGE_CACHABLE 0x008 /* C-bit : cachable */ +#define _PAGE_SZ0 0x010 /* SZ0-bit : Size of page */ +#define _PAGE_RW 0x020 /* PR0-bit : write access allowed */ +#define _PAGE_USER 0x040 /* PR1-bit : user space access allowed*/ +#define _PAGE_SZ1 0x080 /* SZ1-bit : Size of page (on SH-4) */ +#define _PAGE_PRESENT 0x100 /* V-bit : page is valid */ +#define _PAGE_PROTNONE 0x200 /* software: if not present */ +#define _PAGE_ACCESSED 0x400 /* software: page referenced */ +#define _PAGE_FILE _PAGE_WT /* software: pagecache or swap? */ + +#define _PAGE_SZ_MASK (_PAGE_SZ0 | _PAGE_SZ1) +#define _PAGE_PR_MASK (_PAGE_RW | _PAGE_USER) + +/* Extended mode bits */ +#define _PAGE_EXT_ESZ0 0x0010 /* ESZ0-bit: Size of page */ +#define _PAGE_EXT_ESZ1 0x0020 /* ESZ1-bit: Size of page */ +#define _PAGE_EXT_ESZ2 0x0040 /* ESZ2-bit: Size of page */ +#define _PAGE_EXT_ESZ3 0x0080 /* ESZ3-bit: Size of page */ + +#define _PAGE_EXT_USER_EXEC 0x0100 /* EPR0-bit: User space executable */ +#define _PAGE_EXT_USER_WRITE 0x0200 /* EPR1-bit: User space writable */ +#define _PAGE_EXT_USER_READ 0x0400 /* EPR2-bit: User space readable */ + +#define _PAGE_EXT_KERN_EXEC 0x0800 /* EPR3-bit: Kernel space executable */ +#define _PAGE_EXT_KERN_WRITE 0x1000 /* EPR4-bit: Kernel space writable */ +#define _PAGE_EXT_KERN_READ 0x2000 /* EPR5-bit: Kernel space readable */ + +/* Wrapper for extended mode pgprot twiddling */ +#define _PAGE_EXT(x) ((unsigned long long)(x) << 32) + +/* software: moves to PTEA.TC (Timing Control) */ +#define _PAGE_PCC_AREA5 0x00000000 /* use BSC registers for area5 */ +#define _PAGE_PCC_AREA6 0x80000000 /* use BSC registers for area6 */ + +/* software: moves to PTEA.SA[2:0] (Space Attributes) */ +#define _PAGE_PCC_IODYN 0x00000001 /* IO space, dynamically sized bus */ +#define _PAGE_PCC_IO8 0x20000000 /* IO space, 8 bit bus */ +#define _PAGE_PCC_IO16 0x20000001 /* IO space, 16 bit bus */ +#define _PAGE_PCC_COM8 0x40000000 /* Common Memory space, 8 bit bus */ +#define _PAGE_PCC_COM16 0x40000001 /* Common Memory space, 16 bit bus */ +#define _PAGE_PCC_ATR8 0x60000000 /* Attribute Memory space, 8 bit bus */ +#define _PAGE_PCC_ATR16 0x60000001 /* Attribute Memory space, 6 bit bus */ + +/* Mask which drops unused bits from the PTEL value */ +#if defined(CONFIG_CPU_SH3) +#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED| \ + _PAGE_FILE | _PAGE_SZ1 | \ + _PAGE_HW_SHARED) +#elif defined(CONFIG_X2TLB) +/* Get rid of the legacy PR/SZ bits when using extended mode */ +#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | \ + _PAGE_FILE | _PAGE_PR_MASK | _PAGE_SZ_MASK) +#else +#define _PAGE_CLEAR_FLAGS (_PAGE_PROTNONE | _PAGE_ACCESSED | _PAGE_FILE) +#endif + +#define _PAGE_FLAGS_HARDWARE_MASK (PHYS_ADDR_MASK & ~(_PAGE_CLEAR_FLAGS)) + +/* Hardware flags, page size encoding */ +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ0) +# elif defined(CONFIG_PAGE_SIZE_8KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ1) +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_EXT(_PAGE_EXT_ESZ2) +# endif +#else +# if defined(CONFIG_PAGE_SIZE_4KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ0 +# elif defined(CONFIG_PAGE_SIZE_64KB) +# define _PAGE_FLAGS_HARD _PAGE_SZ1 +# endif +#endif + +#if defined(CONFIG_X2TLB) +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256K) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ0 | _PAGE_EXT_ESZ1 | _PAGE_EXT_ESZ2) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ3) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB) +# define _PAGE_SZHUGE (_PAGE_EXT_ESZ2 | _PAGE_EXT_ESZ3) +# endif +#else +# if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +# define _PAGE_SZHUGE (_PAGE_SZ1) +# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +# define _PAGE_SZHUGE (_PAGE_SZ0 | _PAGE_SZ1) +# endif +#endif + +/* + * Stub out _PAGE_SZHUGE if we don't have a good definition for it, + * to make pte_mkhuge() happy. + */ +#ifndef _PAGE_SZHUGE +# define _PAGE_SZHUGE (_PAGE_FLAGS_HARD) +#endif + +#define _PAGE_CHG_MASK \ + (PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | _PAGE_DIRTY) + +#ifndef __ASSEMBLY__ + +#if defined(CONFIG_X2TLB) /* SH-X2 TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_WRITE)) + +#define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_EXEC | \ + _PAGE_EXT_KERN_READ | \ + _PAGE_EXT_USER_EXEC | \ + _PAGE_EXT_USER_READ)) + +#define PAGE_COPY PAGE_EXECREAD + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_USER_READ)) + +#define PAGE_WRITEONLY __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_USER_WRITE)) + +#define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \ + _PAGE_CACHABLE | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_EXEC | \ + _PAGE_EXT_USER_WRITE | \ + _PAGE_EXT_USER_READ | \ + _PAGE_EXT_USER_EXEC)) + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_NOCACHE \ + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_EXEC)) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(_PAGE_PRESENT | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + _PAGE_EXT(_PAGE_EXT_KERN_READ | \ + _PAGE_EXT_KERN_WRITE | \ + _PAGE_EXT_KERN_EXEC) \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) + +#elif defined(CONFIG_MMU) /* SH-X TLB */ +#define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ + _PAGE_CACHABLE | _PAGE_ACCESSED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD) + +#define PAGE_EXECREAD PAGE_READONLY +#define PAGE_RWX PAGE_SHARED +#define PAGE_WRITEONLY PAGE_SHARED + +#define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_NOCACHE \ + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_HW_SHARED | \ + _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_CACHABLE | \ + _PAGE_DIRTY | _PAGE_ACCESSED | \ + _PAGE_HW_SHARED | _PAGE_FLAGS_HARD) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | \ + _PAGE_ACCESSED | _PAGE_FLAGS_HARD | \ + (slot ? _PAGE_PCC_AREA5 : _PAGE_PCC_AREA6) | \ + (type)) +#else /* no mmu */ +#define PAGE_NONE __pgprot(0) +#define PAGE_SHARED __pgprot(0) +#define PAGE_COPY __pgprot(0) +#define PAGE_EXECREAD __pgprot(0) +#define PAGE_RWX __pgprot(0) +#define PAGE_READONLY __pgprot(0) +#define PAGE_WRITEONLY __pgprot(0) +#define PAGE_KERNEL __pgprot(0) +#define PAGE_KERNEL_NOCACHE __pgprot(0) +#define PAGE_KERNEL_RO __pgprot(0) + +#define PAGE_KERNEL_PCC(slot, type) \ + __pgprot(0) +#endif + +#endif /* __ASSEMBLY__ */ + +#ifndef __ASSEMBLY__ + +/* + * Certain architectures need to do special things when PTEs + * within a page table are directly modified. Thus, the following + * hook is made available. + */ +#ifdef CONFIG_X2TLB +static inline void set_pte(pte_t *ptep, pte_t pte) +{ + ptep->pte_high = pte.pte_high; + smp_wmb(); + ptep->pte_low = pte.pte_low; +} +#else +#define set_pte(pteptr, pteval) (*(pteptr) = pteval) +#endif + +#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) + +/* + * (pmds are folded into pgds so this doesn't get actually called, + * but the define is needed for a generic inline function.) + */ +#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) + +#define pfn_pte(pfn, prot) \ + __pte(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) \ + __pmd(((unsigned long long)(pfn) << PAGE_SHIFT) | pgprot_val(prot)) + +#define pte_none(x) (!pte_val(x)) +#define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE)) + +#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)) +#define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0) +#define pmd_bad(x) (pmd_val(x) & ~PAGE_MASK) + +#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) +#define pte_page(x) pfn_to_page(pte_pfn(x)) + +/* + * The following only work if pte_present() is true. + * Undefined behaviour if not.. + */ +#define pte_not_present(pte) (!((pte).pte_low & _PAGE_PRESENT)) +#define pte_dirty(pte) ((pte).pte_low & _PAGE_DIRTY) +#define pte_young(pte) ((pte).pte_low & _PAGE_ACCESSED) +#define pte_file(pte) ((pte).pte_low & _PAGE_FILE) + +#ifdef CONFIG_X2TLB +#define pte_write(pte) ((pte).pte_high & _PAGE_EXT_USER_WRITE) +#else +#define pte_write(pte) ((pte).pte_low & _PAGE_RW) +#endif + +#define PTE_BIT_FUNC(h,fn,op) \ +static inline pte_t pte_##fn(pte_t pte) { pte.pte_##h op; return pte; } + +#ifdef CONFIG_X2TLB +/* + * We cheat a bit in the SH-X2 TLB case. As the permission bits are + * individually toggled (and user permissions are entirely decoupled from + * kernel permissions), we attempt to couple them a bit more sanely here. + */ +PTE_BIT_FUNC(high, wrprotect, &= ~_PAGE_EXT_USER_WRITE); +PTE_BIT_FUNC(high, mkwrite, |= _PAGE_EXT_USER_WRITE | _PAGE_EXT_KERN_WRITE); +PTE_BIT_FUNC(high, mkhuge, |= _PAGE_SZHUGE); +#else +PTE_BIT_FUNC(low, wrprotect, &= ~_PAGE_RW); +PTE_BIT_FUNC(low, mkwrite, |= _PAGE_RW); +PTE_BIT_FUNC(low, mkhuge, |= _PAGE_SZHUGE); +#endif + +PTE_BIT_FUNC(low, mkclean, &= ~_PAGE_DIRTY); +PTE_BIT_FUNC(low, mkdirty, |= _PAGE_DIRTY); +PTE_BIT_FUNC(low, mkold, &= ~_PAGE_ACCESSED); +PTE_BIT_FUNC(low, mkyoung, |= _PAGE_ACCESSED); + +/* + * Macro and implementation to make a page protection as uncachable. + */ +#define pgprot_writecombine(prot) \ + __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) + +#define pgprot_noncached pgprot_writecombine + +/* + * Conversion functions: convert a page and protection to a page entry, + * and a page entry and page directory to the page they refer to. + * + * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) + */ +#define mk_pte(page, pgprot) pfn_pte(page_to_pfn(page), (pgprot)) + +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ + pte.pte_low &= _PAGE_CHG_MASK; + pte.pte_low |= pgprot_val(newprot); + +#ifdef CONFIG_X2TLB + pte.pte_high |= pgprot_val(newprot) >> 32; +#endif + + return pte; +} + +#define pmd_page_vaddr(pmd) ((unsigned long)pmd_val(pmd)) +#define pmd_page(pmd) (virt_to_page(pmd_val(pmd))) + +/* to find an entry in a page-table-directory. */ +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) + +/* to find an entry in a kernel page-table-directory */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +/* Find an entry in the third-level page table.. */ +#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)) +#define pte_offset_map(dir, address) pte_offset_kernel(dir, address) +#define pte_offset_map_nested(dir, address) pte_offset_kernel(dir, address) + +#define pte_unmap(pte) do { } while (0) +#define pte_unmap_nested(pte) do { } while (0) + +#ifdef CONFIG_X2TLB +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %p(%08lx%08lx).\n", __FILE__, __LINE__, \ + &(e), (e).pte_high, (e).pte_low) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %016llx.\n", __FILE__, __LINE__, pgd_val(e)) +#else +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) +#endif + +/* + * Encode and de-code a swap entry + * + * Constraints: + * _PAGE_FILE at bit 0 + * _PAGE_PRESENT at bit 8 + * _PAGE_PROTNONE at bit 9 + * + * For the normal case, we encode the swap type into bits 0:7 and the + * swap offset into bits 10:30. For the 64-bit PTE case, we keep the + * preserved bits in the low 32-bits and use the upper 32 as the swap + * offset (along with a 5-bit type), following the same approach as x86 + * PAE. This keeps the logic quite simple, and allows for a full 32 + * PTE_FILE_MAX_BITS, as opposed to the 29-bits we're constrained with + * in the pte_low case. + * + * As is evident by the Alpha code, if we ever get a 64-bit unsigned + * long (swp_entry_t) to match up with the 64-bit PTEs, this all becomes + * much cleaner.. + * + * NOTE: We should set ZEROs at the position of _PAGE_PRESENT + * and _PAGE_PROTNONE bits + */ +#ifdef CONFIG_X2TLB +#define __swp_type(x) ((x).val & 0x1f) +#define __swp_offset(x) ((x).val >> 5) +#define __swp_entry(type, offset) ((swp_entry_t){ (type) | (offset) << 5}) +#define __pte_to_swp_entry(pte) ((swp_entry_t){ (pte).pte_high }) +#define __swp_entry_to_pte(x) ((pte_t){ 0, (x).val }) + +/* + * Encode and decode a nonlinear file mapping entry + */ +#define pte_to_pgoff(pte) ((pte).pte_high) +#define pgoff_to_pte(off) ((pte_t) { _PAGE_FILE, (off) }) + +#define PTE_FILE_MAX_BITS 32 +#else +#define __swp_type(x) ((x).val & 0xff) +#define __swp_offset(x) ((x).val >> 10) +#define __swp_entry(type, offset) ((swp_entry_t){(type) | (offset) <<10}) + +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 1 }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 1 }) + +/* + * Encode and decode a nonlinear file mapping entry + */ +#define PTE_FILE_MAX_BITS 29 +#define pte_to_pgoff(pte) (pte_val(pte) >> 1) +#define pgoff_to_pte(off) ((pte_t) { ((off) << 1) | _PAGE_FILE }) +#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_SH_PGTABLE_32_H */ diff -puN /dev/null include/asm-sh/pgtable_64.h --- /dev/null +++ a/include/asm-sh/pgtable_64.h @@ -0,0 +1,299 @@ +#ifndef __ASM_SH_PGTABLE_64_H +#define __ASM_SH_PGTABLE_64_H + +/* + * include/asm-sh/pgtable_64.h + * + * This file contains the functions and defines necessary to modify and use + * the SuperH page table tree. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * Copyright (C) 2003, 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include +#include + +/* + * Error outputs. + */ +#define pte_ERROR(e) \ + printk("%s:%d: bad pte %016Lx.\n", __FILE__, __LINE__, pte_val(e)) +#define pgd_ERROR(e) \ + printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e)) + +/* + * Table setting routines. Used within arch/mm only. + */ +#define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval) + +static __inline__ void set_pte(pte_t *pteptr, pte_t pteval) +{ + unsigned long long x = ((unsigned long long) pteval.pte_low); + unsigned long long *xp = (unsigned long long *) pteptr; + /* + * Sign-extend based on NPHYS. + */ + *(xp) = (x & NPHYS_SIGN) ? (x | NPHYS_MASK) : x; +} +#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval) + +static __inline__ void pmd_set(pmd_t *pmdp,pte_t *ptep) +{ + pmd_val(*pmdp) = (unsigned long) ptep; +} + +/* + * PGD defines. Top level. + */ + +/* To find an entry in a generic PGD. */ +#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) +#define __pgd_offset(address) pgd_index(address) +#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) + +/* To find an entry in a kernel PGD. */ +#define pgd_offset_k(address) pgd_offset(&init_mm, address) + +/* + * PMD level access routines. Same notes as above. + */ +#define _PMD_EMPTY 0x0 +/* Either the PMD is empty or present, it's not paged out */ +#define pmd_present(pmd_entry) (pmd_val(pmd_entry) & _PAGE_PRESENT) +#define pmd_clear(pmd_entry_p) (set_pmd((pmd_entry_p), __pmd(_PMD_EMPTY))) +#define pmd_none(pmd_entry) (pmd_val((pmd_entry)) == _PMD_EMPTY) +#define pmd_bad(pmd_entry) ((pmd_val(pmd_entry) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) + +#define pmd_page_vaddr(pmd_entry) \ + ((unsigned long) __va(pmd_val(pmd_entry) & PAGE_MASK)) + +#define pmd_page(pmd) \ + (virt_to_page(pmd_val(pmd))) + +/* PMD to PTE dereferencing */ +#define pte_index(address) \ + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) + +#define pte_offset_kernel(dir, addr) \ + ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr))) + +#define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) +#define pte_offset_map_nested(dir,addr) pte_offset_kernel(dir, addr) +#define pte_unmap(pte) do { } while (0) +#define pte_unmap_nested(pte) do { } while (0) + +#ifndef __ASSEMBLY__ +#define IOBASE_VADDR 0xff000000 +#define IOBASE_END 0xffffffff + +/* + * PTEL coherent flags. + * See Chapter 17 ST50 CPU Core Volume 1, Architecture. + */ +/* The bits that are required in the SH-5 TLB are placed in the h/w-defined + positions, to avoid expensive bit shuffling on every refill. The remaining + bits are used for s/w purposes and masked out on each refill. + + Note, the PTE slots are used to hold data of type swp_entry_t when a page is + swapped out. Only the _PAGE_PRESENT flag is significant when the page is + swapped out, and it must be placed so that it doesn't overlap either the + type or offset fields of swp_entry_t. For x86, offset is at [31:8] and type + at [6:1], with _PAGE_PRESENT at bit 0 for both pte_t and swp_entry_t. This + scheme doesn't map to SH-5 because bit [0] controls cacheability. So bit + [2] is used for _PAGE_PRESENT and the type field of swp_entry_t is split + into 2 pieces. That is handled by SWP_ENTRY and SWP_TYPE below. */ +#define _PAGE_WT 0x001 /* CB0: if cacheable, 1->write-thru, 0->write-back */ +#define _PAGE_DEVICE 0x001 /* CB0: if uncacheable, 1->device (i.e. no write-combining or reordering at bus level) */ +#define _PAGE_CACHABLE 0x002 /* CB1: uncachable/cachable */ +#define _PAGE_PRESENT 0x004 /* software: page referenced */ +#define _PAGE_FILE 0x004 /* software: only when !present */ +#define _PAGE_SIZE0 0x008 /* SZ0-bit : size of page */ +#define _PAGE_SIZE1 0x010 /* SZ1-bit : size of page */ +#define _PAGE_SHARED 0x020 /* software: reflects PTEH's SH */ +#define _PAGE_READ 0x040 /* PR0-bit : read access allowed */ +#define _PAGE_EXECUTE 0x080 /* PR1-bit : execute access allowed */ +#define _PAGE_WRITE 0x100 /* PR2-bit : write access allowed */ +#define _PAGE_USER 0x200 /* PR3-bit : user space access allowed */ +#define _PAGE_DIRTY 0x400 /* software: page accessed in write */ +#define _PAGE_ACCESSED 0x800 /* software: page referenced */ + +/* Mask which drops software flags */ +#define _PAGE_FLAGS_HARDWARE_MASK 0xfffffffffffff3dbLL + +/* + * HugeTLB support + */ +#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) +#define _PAGE_SZHUGE (_PAGE_SIZE0) +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) +#define _PAGE_SZHUGE (_PAGE_SIZE1) +#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512MB) +#define _PAGE_SZHUGE (_PAGE_SIZE0 | _PAGE_SIZE1) +#endif + +/* + * Default flags for a Kernel page. + * This is fundametally also SHARED because the main use of this define + * (other than for PGD/PMD entries) is for the VMALLOC pool which is + * contextless. + * + * _PAGE_EXECUTE is required for modules + * + */ +#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ + _PAGE_EXECUTE | \ + _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_DIRTY | \ + _PAGE_SHARED) + +/* Default flags for a User page */ +#define _PAGE_TABLE (_KERNPG_TABLE | _PAGE_USER) + +#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) + +/* + * We have full permissions (Read/Write/Execute/Shared). + */ +#define _PAGE_COMMON (_PAGE_PRESENT | _PAGE_USER | \ + _PAGE_CACHABLE | _PAGE_ACCESSED) + +#define PAGE_NONE __pgprot(_PAGE_CACHABLE | _PAGE_ACCESSED) +#define PAGE_SHARED __pgprot(_PAGE_COMMON | _PAGE_READ | _PAGE_WRITE | \ + _PAGE_SHARED) +#define PAGE_EXECREAD __pgprot(_PAGE_COMMON | _PAGE_READ | _PAGE_EXECUTE) + +/* + * We need to include PAGE_EXECUTE in PAGE_COPY because it is the default + * protection mode for the stack. + */ +#define PAGE_COPY PAGE_EXECREAD + +#define PAGE_READONLY __pgprot(_PAGE_COMMON | _PAGE_READ) +#define PAGE_WRITEONLY __pgprot(_PAGE_COMMON | _PAGE_WRITE) +#define PAGE_RWX __pgprot(_PAGE_COMMON | _PAGE_READ | \ + _PAGE_WRITE | _PAGE_EXECUTE) +#define PAGE_KERNEL __pgprot(_KERNPG_TABLE) + +/* Make it a device mapping for maximum safety (e.g. for mapping device + registers into user-space via /dev/map). */ +#define pgprot_noncached(x) __pgprot(((x).pgprot & ~(_PAGE_CACHABLE)) | _PAGE_DEVICE) +#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) + +/* + * Handling allocation failures during page table setup. + */ +extern void __handle_bad_pmd_kernel(pmd_t * pmd); +#define __handle_bad_pmd(x) __handle_bad_pmd_kernel(x) + +/* + * PTE level access routines. + * + * Note1: + * It's the tree walk leaf. This is physical address to be stored. + * + * Note 2: + * Regarding the choice of _PTE_EMPTY: + + We must choose a bit pattern that cannot be valid, whether or not the page + is present. bit[2]==1 => present, bit[2]==0 => swapped out. If swapped + out, bits [31:8], [6:3], [1:0] are under swapper control, so only bit[7] is + left for us to select. If we force bit[7]==0 when swapped out, we could use + the combination bit[7,2]=2'b10 to indicate an empty PTE. Alternatively, if + we force bit[7]==1 when swapped out, we can use all zeroes to indicate + empty. This is convenient, because the page tables get cleared to zero + when they are allocated. + + */ +#define _PTE_EMPTY 0x0 +#define pte_present(x) (pte_val(x) & _PAGE_PRESENT) +#define pte_clear(mm,addr,xp) (set_pte_at(mm, addr, xp, __pte(_PTE_EMPTY))) +#define pte_none(x) (pte_val(x) == _PTE_EMPTY) + +/* + * Some definitions to translate between mem_map, PTEs, and page + * addresses: + */ + +/* + * Given a PTE, return the index of the mem_map[] entry corresponding + * to the page frame the PTE. Get the absolute physical address, make + * a relative physical address and translate it to an index. + */ +#define pte_pagenr(x) (((unsigned long) (pte_val(x)) - \ + __MEMORY_START) >> PAGE_SHIFT) + +/* + * Given a PTE, return the "struct page *". + */ +#define pte_page(x) (mem_map + pte_pagenr(x)) + +/* + * Return number of (down rounded) MB corresponding to x pages. + */ +#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) + + +/* + * The following have defined behavior only work if pte_present() is true. + */ +static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; } +static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; } +static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } +static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; } + +static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; } +static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; } +static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } +static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; } +static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } +static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } +static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } + + +/* + * Conversion functions: convert a page and protection to a page entry. + * + * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) + */ +#define mk_pte(page,pgprot) \ +({ \ + pte_t __pte; \ + \ + set_pte(&__pte, __pte((((page)-mem_map) << PAGE_SHIFT) | \ + __MEMORY_START | pgprot_val((pgprot)))); \ + __pte; \ +}) + +/* + * This takes a (absolute) physical page address that is used + * by the remapping functions + */ +#define mk_pte_phys(physpage, pgprot) \ +({ pte_t __pte; set_pte(&__pte, __pte(physpage | pgprot_val(pgprot))); __pte; }) + +static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) +{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } + +/* Encode and decode a swap entry */ +#define __swp_type(x) (((x).val & 3) + (((x).val >> 1) & 0x3c)) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((offset << 8) + ((type & 0x3c) << 1) + (type & 3)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) + +/* Encode and decode a nonlinear file mapping entry */ +#define PTE_FILE_MAX_BITS 29 +#define pte_to_pgoff(pte) (pte_val(pte)) +#define pgoff_to_pte(off) ((pte_t) { (off) | _PAGE_FILE }) + +#endif /* !__ASSEMBLY__ */ + +#define pfn_pte(pfn, prot) __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) +#define pfn_pmd(pfn, prot) __pmd(((pfn) << PAGE_SHIFT) | pgprot_val(prot)) + +#endif /* __ASM_SH_PGTABLE_64_H */ diff -puN include/asm-sh/processor.h~git-sh include/asm-sh/processor.h --- a/include/asm-sh/processor.h~git-sh +++ a/include/asm-sh/processor.h @@ -1,32 +1,10 @@ -/* - * include/asm-sh/processor.h - * - * Copyright (C) 1999, 2000 Niibe Yutaka - * Copyright (C) 2002, 2003 Paul Mundt - */ - #ifndef __ASM_SH_PROCESSOR_H #define __ASM_SH_PROCESSOR_H -#ifdef __KERNEL__ -#include -#include -#include -#include -#include #include +#include -/* - * Default implementation of macro that returns current - * instruction pointer ("program counter"). - */ -#define current_text_addr() ({ void *pc; __asm__("mova 1f, %0\n1:":"=z" (pc)); pc; }) - -/* Core Processor Version Register */ -#define CCN_PVR 0xff000030 -#define CCN_CVR 0xff000040 -#define CCN_PRR 0xff000044 - +#ifndef __ASSEMBLY__ /* * CPU type and hardware bug flags. Kept separately for each CPU. * @@ -39,7 +17,7 @@ enum cpu_type { CPU_SH7619, /* SH-2A types */ - CPU_SH7206, + CPU_SH7203, CPU_SH7206, CPU_SH7263, /* SH-3 types */ CPU_SH7705, CPU_SH7706, CPU_SH7707, @@ -57,229 +35,31 @@ enum cpu_type { /* SH4AL-DSP types */ CPU_SH7343, CPU_SH7722, + /* SH-5 types */ + CPU_SH5_101, CPU_SH5_103, + /* Unknown subtype */ CPU_SH_NONE }; -struct sh_cpuinfo { - unsigned int type; - unsigned long loops_per_jiffy; - unsigned long asid_cache; - - struct cache_info icache; /* Primary I-cache */ - struct cache_info dcache; /* Primary D-cache */ - struct cache_info scache; /* Secondary cache */ - - unsigned long flags; -} __attribute__ ((aligned(L1_CACHE_BYTES))); - -extern struct sh_cpuinfo cpu_data[]; -#define boot_cpu_data cpu_data[0] -#define current_cpu_data cpu_data[smp_processor_id()] -#define raw_current_cpu_data cpu_data[raw_smp_processor_id()] - -/* - * User space process size: 2GB. - * - * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff - */ -#define TASK_SIZE 0x7c000000UL - -/* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) - -/* - * Bit of SR register - * - * FD-bit: - * When it's set, it means the processor doesn't have right to use FPU, - * and it results exception when the floating operation is executed. - * - * IMASK-bit: - * Interrupt level mask - */ -#define SR_FD 0x00008000 -#define SR_DSP 0x00001000 -#define SR_IMASK 0x000000f0 - -/* - * FPU structure and data - */ - -struct sh_fpu_hard_struct { - unsigned long fp_regs[16]; - unsigned long xfp_regs[16]; - unsigned long fpscr; - unsigned long fpul; - - long status; /* software status information */ -}; - -/* Dummy fpu emulator */ -struct sh_fpu_soft_struct { - unsigned long fp_regs[16]; - unsigned long xfp_regs[16]; - unsigned long fpscr; - unsigned long fpul; - - unsigned char lookahead; - unsigned long entry_pc; -}; - -union sh_fpu_union { - struct sh_fpu_hard_struct hard; - struct sh_fpu_soft_struct soft; -}; - -struct thread_struct { - /* Saved registers when thread is descheduled */ - unsigned long sp; - unsigned long pc; +/* Forward decl */ +struct sh_cpuinfo; - /* Hardware debugging registers */ - unsigned long ubc_pc; - - /* floating point info */ - union sh_fpu_union fpu; -}; - -typedef struct { - unsigned long seg; -} mm_segment_t; - -/* Count of active tasks with UBC settings */ -extern int ubc_usercnt; - -#define INIT_THREAD { \ - .sp = sizeof(init_stack) + (long) &init_stack, \ -} - -/* - * Do necessary setup to start up a newly executed thread. - */ -#define start_thread(regs, new_pc, new_sp) \ - set_fs(USER_DS); \ - regs->pr = 0; \ - regs->sr = SR_FD; /* User mode. */ \ - regs->pc = new_pc; \ - regs->regs[15] = new_sp - -/* Forward declaration, a strange C thing */ -struct task_struct; -struct mm_struct; - -/* Free all resources held by a thread. */ -extern void release_thread(struct task_struct *); - -/* Prepare to copy thread state - unlazy all lazy status */ -#define prepare_to_copy(tsk) do { } while (0) - -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - -/* Copy and release all segment info associated with a VM */ -#define copy_segments(p, mm) do { } while(0) -#define release_segments(mm) do { } while(0) - -/* - * FPU lazy state save handling. - */ - -static __inline__ void disable_fpu(void) -{ - unsigned long __dummy; - - /* Set FD flag in SR */ - __asm__ __volatile__("stc sr, %0\n\t" - "or %1, %0\n\t" - "ldc %0, sr" - : "=&r" (__dummy) - : "r" (SR_FD)); -} - -static __inline__ void enable_fpu(void) -{ - unsigned long __dummy; - - /* Clear out FD flag in SR */ - __asm__ __volatile__("stc sr, %0\n\t" - "and %1, %0\n\t" - "ldc %0, sr" - : "=&r" (__dummy) - : "r" (~SR_FD)); -} - -static __inline__ void release_fpu(struct pt_regs *regs) -{ - regs->sr |= SR_FD; -} - -static __inline__ void grab_fpu(struct pt_regs *regs) -{ - regs->sr &= ~SR_FD; -} - -extern void save_fpu(struct task_struct *__tsk, struct pt_regs *regs); - -#define unlazy_fpu(tsk, regs) do { \ - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - save_fpu(tsk, regs); \ - } \ -} while (0) - -#define clear_fpu(tsk, regs) do { \ - if (test_tsk_thread_flag(tsk, TIF_USEDFPU)) { \ - clear_tsk_thread_flag(tsk, TIF_USEDFPU); \ - release_fpu(regs); \ - } \ -} while (0) - -/* Double presision, NANS as NANS, rounding to nearest, no exceptions */ -#define FPSCR_INIT 0x00080000 - -#define FPSCR_CAUSE_MASK 0x0001f000 /* Cause bits */ -#define FPSCR_FLAG_MASK 0x0000007c /* Flag bits */ - -/* - * Return saved PC of a blocked thread. - */ -#define thread_saved_pc(tsk) (tsk->thread.pc) - -void show_trace(struct task_struct *tsk, unsigned long *sp, - struct pt_regs *regs); -extern unsigned long get_wchan(struct task_struct *p); - -#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) -#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) - -#define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory") -#define cpu_relax() barrier() - -#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ - defined(CONFIG_CPU_SH4) -#define PREFETCH_STRIDE L1_CACHE_BYTES -#define ARCH_HAS_PREFETCH -#define ARCH_HAS_PREFETCHW -static inline void prefetch(void *x) -{ - __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory"); -} - -#define prefetchw(x) prefetch(x) -#endif +/* arch/sh/kernel/setup.c */ +const char *get_cpu_subtype(struct sh_cpuinfo *c); #ifdef CONFIG_VSYSCALL -extern int vsyscall_init(void); +int vsyscall_init(void); #else #define vsyscall_init() do { } while (0) #endif -/* arch/sh/kernel/setup.c */ -const char *get_cpu_subtype(struct sh_cpuinfo *c); +#endif /* __ASSEMBLY__ */ + +#ifdef CONFIG_SUPERH32 +# include "processor_32.h" +#else +# include "processor_64.h" +#endif -#endif /* __KERNEL__ */ #endif /* __ASM_SH_PROCESSOR_H */ diff -puN /dev/null include/asm-sh/processor_32.h --- /dev/null +++ a/include/asm-sh/processor_32.h @@ -0,0 +1,215 @@ +/* + * include/asm-sh/processor.h + * + * Copyright (C) 1999, 2000 Niibe Yutaka + * Copyright (C) 2002, 2003 Paul Mundt + */ + +#ifndef __ASM_SH_PROCESSOR_32_H +#define __ASM_SH_PROCESSOR_32_H +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ void *pc; __asm__("mova 1f, %0\n1:":"=z" (pc)); pc; }) + +/* Core Processor Version Register */ +#define CCN_PVR 0xff000030 +#define CCN_CVR 0xff000040 +#define CCN_PRR 0xff000044 + +struct sh_cpuinfo { + unsigned int type; + unsigned long loops_per_jiffy; + unsigned long asid_cache; + + struct cache_info icache; /* Primary I-cache */ + struct cache_info dcache; /* Primary D-cache */ + struct cache_info scache; /* Secondary cache */ + + unsigned long flags; +} __attribute__ ((aligned(L1_CACHE_BYTES))); + +extern struct sh_cpuinfo cpu_data[]; +#define boot_cpu_data cpu_data[0] +#define current_cpu_data cpu_data[smp_processor_id()] +#define raw_current_cpu_data cpu_data[raw_smp_processor_id()] + +/* + * User space process size: 2GB. + * + * Since SH7709 and SH7750 have "area 7", we can't use 0x7c000000--0x7fffffff + */ +#define TASK_SIZE 0x7c000000UL + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +/* + * Bit of SR register + * + * FD-bit: + * When it's set, it means the processor doesn't have right to use FPU, + * and it results exception when the floating operation is executed. + * + * IMASK-bit: + * Interrupt level mask + */ +#define SR_DSP 0x00001000 +#define SR_IMASK 0x000000f0 + +/* + * FPU structure and data + */ + +struct sh_fpu_hard_struct { + unsigned long fp_regs[16]; + unsigned long xfp_regs[16]; + unsigned long fpscr; + unsigned long fpul; + + long status; /* software status information */ +}; + +/* Dummy fpu emulator */ +struct sh_fpu_soft_struct { + unsigned long fp_regs[16]; + unsigned long xfp_regs[16]; + unsigned long fpscr; + unsigned long fpul; + + unsigned char lookahead; + unsigned long entry_pc; +}; + +union sh_fpu_union { + struct sh_fpu_hard_struct hard; + struct sh_fpu_soft_struct soft; +}; + +struct thread_struct { + /* Saved registers when thread is descheduled */ + unsigned long sp; + unsigned long pc; + + /* Hardware debugging registers */ + unsigned long ubc_pc; + + /* floating point info */ + union sh_fpu_union fpu; +}; + +typedef struct { + unsigned long seg; +} mm_segment_t; + +/* Count of active tasks with UBC settings */ +extern int ubc_usercnt; + +#define INIT_THREAD { \ + .sp = sizeof(init_stack) + (long) &init_stack, \ +} + +/* + * Do necessary setup to start up a newly executed thread. + */ +#define start_thread(regs, new_pc, new_sp) \ + set_fs(USER_DS); \ + regs->pr = 0; \ + regs->sr = SR_FD; /* User mode. */ \ + regs->pc = new_pc; \ + regs->regs[15] = new_sp + +/* Forward declaration, a strange C thing */ +struct task_struct; +struct mm_struct; + +/* Free all resources held by a thread. */ +extern void release_thread(struct task_struct *); + +/* Prepare to copy thread state - unlazy all lazy status */ +#define prepare_to_copy(tsk) do { } while (0) + +/* + * create a kernel thread without removing it from tasklists + */ +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + +/* Copy and release all segment info associated with a VM */ +#define copy_segments(p, mm) do { } while(0) +#define release_segments(mm) do { } while(0) + +/* + * FPU lazy state save handling. + */ + +static __inline__ void disable_fpu(void) +{ + unsigned long __dummy; + + /* Set FD flag in SR */ + __asm__ __volatile__("stc sr, %0\n\t" + "or %1, %0\n\t" + "ldc %0, sr" + : "=&r" (__dummy) + : "r" (SR_FD)); +} + +static __inline__ void enable_fpu(void) +{ + unsigned long __dummy; + + /* Clear out FD flag in SR */ + __asm__ __volatile__("stc sr, %0\n\t" + "and %1, %0\n\t" + "ldc %0, sr" + : "=&r" (__dummy) + : "r" (~SR_FD)); +} + +/* Double presision, NANS as NANS, rounding to nearest, no exceptions */ +#define FPSCR_INIT 0x00080000 + +#define FPSCR_CAUSE_MASK 0x0001f000 /* Cause bits */ +#define FPSCR_FLAG_MASK 0x0000007c /* Flag bits */ + +/* + * Return saved PC of a blocked thread. + */ +#define thread_saved_pc(tsk) (tsk->thread.pc) + +void show_trace(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs); +extern unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->regs[15]) + +#define cpu_sleep() __asm__ __volatile__ ("sleep" : : : "memory") +#define cpu_relax() barrier() + +#if defined(CONFIG_CPU_SH2A) || defined(CONFIG_CPU_SH3) || \ + defined(CONFIG_CPU_SH4) +#define PREFETCH_STRIDE L1_CACHE_BYTES +#define ARCH_HAS_PREFETCH +#define ARCH_HAS_PREFETCHW +static inline void prefetch(void *x) +{ + __asm__ __volatile__ ("pref @%0\n\t" : : "r" (x) : "memory"); +} + +#define prefetchw(x) prefetch(x) +#endif + +#endif /* __KERNEL__ */ +#endif /* __ASM_SH_PROCESSOR_32_H */ diff -puN /dev/null include/asm-sh/processor_64.h --- /dev/null +++ a/include/asm-sh/processor_64.h @@ -0,0 +1,275 @@ +#ifndef __ASM_SH_PROCESSOR_64_H +#define __ASM_SH_PROCESSOR_64_H + +/* + * include/asm-sh/processor_64.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASSEMBLY__ + +#include +#include +#include +#include +#include +#include + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ \ +void *pc; \ +unsigned long long __dummy = 0; \ +__asm__("gettr tr0, %1\n\t" \ + "pta 4, tr0\n\t" \ + "gettr tr0, %0\n\t" \ + "ptabs %1, tr0\n\t" \ + :"=r" (pc), "=r" (__dummy) \ + : "1" (__dummy)); \ +pc; }) + +/* + * TLB information structure + * + * Defined for both I and D tlb, per-processor. + */ +struct tlb_info { + unsigned long long next; + unsigned long long first; + unsigned long long last; + + unsigned int entries; + unsigned int step; + + unsigned long flags; +}; + +struct sh_cpuinfo { + enum cpu_type type; + unsigned long loops_per_jiffy; + unsigned long asid_cache; + + unsigned int cpu_clock, master_clock, bus_clock, module_clock; + + /* Cache info */ + struct cache_info icache; + struct cache_info dcache; + struct cache_info scache; + + /* TLB info */ + struct tlb_info itlb; + struct tlb_info dtlb; + + unsigned long flags; +}; + +extern struct sh_cpuinfo cpu_data[]; +#define boot_cpu_data cpu_data[0] +#define current_cpu_data cpu_data[smp_processor_id()] +#define raw_current_cpu_data cpu_data[raw_smp_processor_id()] + +#endif + +/* + * User space process size: 2GB - 4k. + */ +#define TASK_SIZE 0x7ffff000UL + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) + +/* + * Bit of SR register + * + * FD-bit: + * When it's set, it means the processor doesn't have right to use FPU, + * and it results exception when the floating operation is executed. + * + * IMASK-bit: + * Interrupt level mask + * + * STEP-bit: + * Single step bit + * + */ +#if defined(CONFIG_SH64_SR_WATCH) +#define SR_MMU 0x84000000 +#else +#define SR_MMU 0x80000000 +#endif + +#define SR_IMASK 0x000000f0 +#define SR_SSTEP 0x08000000 + +#ifndef __ASSEMBLY__ + +/* + * FPU structure and data : require 8-byte alignment as we need to access it + with fld.p, fst.p + */ + +struct sh_fpu_hard_struct { + unsigned long fp_regs[64]; + unsigned int fpscr; + /* long status; * software status information */ +}; + +#if 0 +/* Dummy fpu emulator */ +struct sh_fpu_soft_struct { + unsigned long long fp_regs[32]; + unsigned int fpscr; + unsigned char lookahead; + unsigned long entry_pc; +}; +#endif + +union sh_fpu_union { + struct sh_fpu_hard_struct hard; + /* 'hard' itself only produces 32 bit alignment, yet we need + to access it using 64 bit load/store as well. */ + unsigned long long alignment_dummy; +}; + +struct thread_struct { + unsigned long sp; + unsigned long pc; + /* This stores the address of the pt_regs built during a context + switch, or of the register save area built for a kernel mode + exception. It is used for backtracing the stack of a sleeping task + or one that traps in kernel mode. */ + struct pt_regs *kregs; + /* This stores the address of the pt_regs constructed on entry from + user mode. It is a fixed value over the lifetime of a process, or + NULL for a kernel thread. */ + struct pt_regs *uregs; + + unsigned long trap_no, error_code; + unsigned long address; + /* Hardware debugging registers may come here */ + + /* floating point info */ + union sh_fpu_union fpu; +}; + +typedef struct { + unsigned long seg; +} mm_segment_t; + +#define INIT_MMAP \ +{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } + +extern struct pt_regs fake_swapper_regs; + +#define INIT_THREAD { \ + .sp = sizeof(init_stack) + \ + (long) &init_stack, \ + .pc = 0, \ + .kregs = &fake_swapper_regs, \ + .uregs = NULL, \ + .trap_no = 0, \ + .error_code = 0, \ + .address = 0, \ + .fpu = { { { 0, } }, } \ +} + +/* + * Do necessary setup to start up a newly executed thread. + */ +#define SR_USER (SR_MMU | SR_FD) + +#define start_thread(regs, new_pc, new_sp) \ + set_fs(USER_DS); \ + regs->sr = SR_USER; /* User mode. */ \ + regs->pc = new_pc - 4; /* Compensate syscall exit */ \ + regs->pc |= 1; /* Set SHmedia ! */ \ + regs->regs[18] = 0; \ + regs->regs[15] = new_sp + +/* Forward declaration, a strange C thing */ +struct task_struct; +struct mm_struct; + +/* Free all resources held by a thread. */ +extern void release_thread(struct task_struct *); +/* + * create a kernel thread without removing it from tasklists + */ +extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); + + +/* Copy and release all segment info associated with a VM */ +#define copy_segments(p, mm) do { } while (0) +#define release_segments(mm) do { } while (0) +#define forget_segments() do { } while (0) +#define prepare_to_copy(tsk) do { } while (0) +/* + * FPU lazy state save handling. + */ + +static inline void disable_fpu(void) +{ + unsigned long long __dummy; + + /* Set FD flag in SR */ + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "or %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy) + : "r" (SR_FD)); +} + +static inline void enable_fpu(void) +{ + unsigned long long __dummy; + + /* Clear out FD flag in SR */ + __asm__ __volatile__("getcon " __SR ", %0\n\t" + "and %0, %1, %0\n\t" + "putcon %0, " __SR "\n\t" + : "=&r" (__dummy) + : "r" (~SR_FD)); +} + +/* Round to nearest, no exceptions on inexact, overflow, underflow, + zero-divide, invalid. Configure option for whether to flush denorms to + zero, or except if a denorm is encountered. */ +#if defined(CONFIG_SH64_FPU_DENORM_FLUSH) +#define FPSCR_INIT 0x00040000 +#else +#define FPSCR_INIT 0x00000000 +#endif + +#ifdef CONFIG_SH_FPU +/* Initialise the FP state of a task */ +void fpinit(struct sh_fpu_hard_struct *fpregs); +#else +#define fpinit(fpregs) do { } while (0) +#endif + +extern struct task_struct *last_task_used_math; + +/* + * Return saved PC of a blocked thread. + */ +#define thread_saved_pc(tsk) (tsk->thread.pc) + +extern unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) ((tsk)->thread.pc) +#define KSTK_ESP(tsk) ((tsk)->thread.sp) + +#define cpu_relax() barrier() + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_SH_PROCESSOR_64_H */ diff -puN include/asm-sh/ptrace.h~git-sh include/asm-sh/ptrace.h --- a/include/asm-sh/ptrace.h~git-sh +++ a/include/asm-sh/ptrace.h @@ -5,7 +5,16 @@ * Copyright (C) 1999, 2000 Niibe Yutaka * */ - +#if defined(__SH5__) || defined(CONFIG_SUPERH64) +struct pt_regs { + unsigned long long pc; + unsigned long long sr; + unsigned long long syscall_nr; + unsigned long long regs[63]; + unsigned long long tregs[8]; + unsigned long long pad[2]; +}; +#else /* * GCC defines register number like this: * ----------------------------- @@ -28,7 +37,7 @@ #define REG_PR 17 #define REG_SR 18 -#define REG_GBR 19 +#define REG_GBR 19 #define REG_MACH 20 #define REG_MACL 21 @@ -80,10 +89,14 @@ struct pt_dspregs { #define PTRACE_GETDSPREGS 55 #define PTRACE_SETDSPREGS 56 +#endif #ifdef __KERNEL__ -#define user_mode(regs) (((regs)->sr & 0x40000000)==0) -#define instruction_pointer(regs) ((regs)->pc) +#include + +#define user_mode(regs) (((regs)->sr & 0x40000000)==0) +#define instruction_pointer(regs) ((unsigned long)(regs)->pc) + extern void show_regs(struct pt_regs *); #ifdef CONFIG_SH_DSP @@ -100,10 +113,13 @@ static inline unsigned long profile_pc(s { unsigned long pc = instruction_pointer(regs); - if (pc >= 0xa0000000UL && pc < 0xc0000000UL) +#ifdef P2SEG + if (pc >= P2SEG && pc < P3SEG) pc -= 0x20000000; +#endif + return pc; } -#endif +#endif /* __KERNEL__ */ #endif /* __ASM_SH_PTRACE_H */ diff -puN include/asm-sh/rtc.h~git-sh include/asm-sh/rtc.h --- a/include/asm-sh/rtc.h~git-sh +++ a/include/asm-sh/rtc.h @@ -11,4 +11,6 @@ struct sh_rtc_platform_info { unsigned long capabilities; }; +#include + #endif /* _ASM_RTC_H */ diff -puN include/asm-sh/scatterlist.h~git-sh include/asm-sh/scatterlist.h --- a/include/asm-sh/scatterlist.h~git-sh +++ a/include/asm-sh/scatterlist.h @@ -13,7 +13,7 @@ struct scatterlist { unsigned int length; }; -#define ISA_DMA_THRESHOLD (0x1fffffff) +#define ISA_DMA_THRESHOLD PHYS_ADDR_MASK /* These macros should be used after a pci_map_sg call has been done * to get bus addresses of each of the SG entries and their lengths. diff -puN include/asm-sh/sections.h~git-sh include/asm-sh/sections.h --- a/include/asm-sh/sections.h~git-sh +++ a/include/asm-sh/sections.h @@ -4,6 +4,7 @@ #include extern long __machvec_start, __machvec_end; +extern char __uncached_start, __uncached_end; extern char _ebss[]; #endif /* __ASM_SH_SECTIONS_H */ diff -puN include/asm-sh/sigcontext.h~git-sh include/asm-sh/sigcontext.h --- a/include/asm-sh/sigcontext.h~git-sh +++ a/include/asm-sh/sigcontext.h @@ -4,6 +4,18 @@ struct sigcontext { unsigned long oldmask; +#if defined(__SH5__) || defined(CONFIG_CPU_SH5) + /* CPU registers */ + unsigned long long sc_regs[63]; + unsigned long long sc_tregs[8]; + unsigned long long sc_pc; + unsigned long long sc_sr; + + /* FPU registers */ + unsigned long long sc_fpregs[32]; + unsigned int sc_fpscr; + unsigned int sc_fpvalid; +#else /* CPU registers */ unsigned long sc_regs[16]; unsigned long sc_pc; @@ -13,7 +25,8 @@ struct sigcontext { unsigned long sc_mach; unsigned long sc_macl; -#if defined(__SH4__) || defined(CONFIG_CPU_SH4) +#if defined(__SH4__) || defined(CONFIG_CPU_SH4) || \ + defined(__SH2A__) || defined(CONFIG_CPU_SH2A) /* FPU registers */ unsigned long sc_fpregs[16]; unsigned long sc_xfpregs[16]; @@ -21,6 +34,7 @@ struct sigcontext { unsigned int sc_fpul; unsigned int sc_ownedfp; #endif +#endif }; #endif /* __ASM_SH_SIGCONTEXT_H */ diff -puN include/asm-sh/stat.h~git-sh include/asm-sh/stat.h --- a/include/asm-sh/stat.h~git-sh +++ a/include/asm-sh/stat.h @@ -15,6 +15,66 @@ struct __old_kernel_stat { unsigned long st_ctime; }; +#if defined(__SH5__) || defined(CONFIG_CPU_SH5) +struct stat { + unsigned short st_dev; + unsigned short __pad1; + unsigned long st_ino; + unsigned short st_mode; + unsigned short st_nlink; + unsigned short st_uid; + unsigned short st_gid; + unsigned short st_rdev; + unsigned short __pad2; + unsigned long st_size; + unsigned long st_blksize; + unsigned long st_blocks; + unsigned long st_atime; + unsigned long st_atime_nsec; + unsigned long st_mtime; + unsigned long st_mtime_nsec; + unsigned long st_ctime; + unsigned long st_ctime_nsec; + unsigned long __unused4; + unsigned long __unused5; +}; + +/* This matches struct stat64 in glibc2.1, hence the absolutely + * insane amounts of padding around dev_t's. + */ +struct stat64 { + unsigned short st_dev; + unsigned char __pad0[10]; + + unsigned long st_ino; + unsigned int st_mode; + unsigned int st_nlink; + + unsigned long st_uid; + unsigned long st_gid; + + unsigned short st_rdev; + unsigned char __pad3[10]; + + long long st_size; + unsigned long st_blksize; + + unsigned long st_blocks; /* Number 512-byte blocks allocated. */ + unsigned long __pad4; /* future possible st_blocks high bits */ + + unsigned long st_atime; + unsigned long st_atime_nsec; + + unsigned long st_mtime; + unsigned long st_mtime_nsec; + + unsigned long st_ctime; + unsigned long st_ctime_nsec; /* will be high 32 bits of ctime someday */ + + unsigned long __unused1; + unsigned long __unused2; +}; +#else struct stat { unsigned long st_dev; unsigned long st_ino; @@ -67,11 +127,12 @@ struct stat64 { unsigned long st_mtime_nsec; unsigned long st_ctime; - unsigned long st_ctime_nsec; + unsigned long st_ctime_nsec; unsigned long long st_ino; }; #define STAT_HAVE_NSEC 1 +#endif #endif /* __ASM_SH_STAT_H */ diff -puN include/asm-sh/string.h~git-sh include/asm-sh/string.h --- a/include/asm-sh/string.h~git-sh +++ a/include/asm-sh/string.h @@ -1,131 +1,5 @@ -#ifndef __ASM_SH_STRING_H -#define __ASM_SH_STRING_H - -#ifdef __KERNEL__ - -/* - * Copyright (C) 1999 Niibe Yutaka - * But consider these trivial functions to be public domain. - */ - -#define __HAVE_ARCH_STRCPY -static inline char *strcpy(char *__dest, const char *__src) -{ - register char *__xdest = __dest; - unsigned long __dummy; - - __asm__ __volatile__("1:\n\t" - "mov.b @%1+, %2\n\t" - "mov.b %2, @%0\n\t" - "cmp/eq #0, %2\n\t" - "bf/s 1b\n\t" - " add #1, %0\n\t" - : "=r" (__dest), "=r" (__src), "=&z" (__dummy) - : "0" (__dest), "1" (__src) - : "memory", "t"); - - return __xdest; -} - -#define __HAVE_ARCH_STRNCPY -static inline char *strncpy(char *__dest, const char *__src, size_t __n) -{ - register char *__xdest = __dest; - unsigned long __dummy; - - if (__n == 0) - return __xdest; - - __asm__ __volatile__( - "1:\n" - "mov.b @%1+, %2\n\t" - "mov.b %2, @%0\n\t" - "cmp/eq #0, %2\n\t" - "bt/s 2f\n\t" - " cmp/eq %5,%1\n\t" - "bf/s 1b\n\t" - " add #1, %0\n" - "2:" - : "=r" (__dest), "=r" (__src), "=&z" (__dummy) - : "0" (__dest), "1" (__src), "r" (__src+__n) - : "memory", "t"); - - return __xdest; -} - -#define __HAVE_ARCH_STRCMP -static inline int strcmp(const char *__cs, const char *__ct) -{ - register int __res; - unsigned long __dummy; - - __asm__ __volatile__( - "mov.b @%1+, %3\n" - "1:\n\t" - "mov.b @%0+, %2\n\t" - "cmp/eq #0, %3\n\t" - "bt 2f\n\t" - "cmp/eq %2, %3\n\t" - "bt/s 1b\n\t" - " mov.b @%1+, %3\n\t" - "add #-2, %1\n\t" - "mov.b @%1, %3\n\t" - "sub %3, %2\n" - "2:" - : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy) - : "0" (__cs), "1" (__ct) - : "t"); - - return __res; -} - -#define __HAVE_ARCH_STRNCMP -static inline int strncmp(const char *__cs, const char *__ct, size_t __n) -{ - register int __res; - unsigned long __dummy; - - if (__n == 0) - return 0; - - __asm__ __volatile__( - "mov.b @%1+, %3\n" - "1:\n\t" - "mov.b @%0+, %2\n\t" - "cmp/eq %6, %0\n\t" - "bt/s 2f\n\t" - " cmp/eq #0, %3\n\t" - "bt/s 3f\n\t" - " cmp/eq %3, %2\n\t" - "bt/s 1b\n\t" - " mov.b @%1+, %3\n\t" - "add #-2, %1\n\t" - "mov.b @%1, %3\n" - "2:\n\t" - "sub %3, %2\n" - "3:" - :"=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy) - : "0" (__cs), "1" (__ct), "r" (__cs+__n) - : "t"); - - return __res; -} - -#define __HAVE_ARCH_MEMSET -extern void *memset(void *__s, int __c, size_t __count); - -#define __HAVE_ARCH_MEMCPY -extern void *memcpy(void *__to, __const__ void *__from, size_t __n); - -#define __HAVE_ARCH_MEMMOVE -extern void *memmove(void *__dest, __const__ void *__src, size_t __n); - -#define __HAVE_ARCH_MEMCHR -extern void *memchr(const void *__s, int __c, size_t __n); - -#define __HAVE_ARCH_STRLEN -extern size_t strlen(const char *); - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH_STRING_H */ +#ifdef CONFIG_SUPERH32 +# include "string_32.h" +#else +# include "string_64.h" +#endif diff -puN /dev/null include/asm-sh/string_32.h --- /dev/null +++ a/include/asm-sh/string_32.h @@ -0,0 +1,131 @@ +#ifndef __ASM_SH_STRING_H +#define __ASM_SH_STRING_H + +#ifdef __KERNEL__ + +/* + * Copyright (C) 1999 Niibe Yutaka + * But consider these trivial functions to be public domain. + */ + +#define __HAVE_ARCH_STRCPY +static inline char *strcpy(char *__dest, const char *__src) +{ + register char *__xdest = __dest; + unsigned long __dummy; + + __asm__ __volatile__("1:\n\t" + "mov.b @%1+, %2\n\t" + "mov.b %2, @%0\n\t" + "cmp/eq #0, %2\n\t" + "bf/s 1b\n\t" + " add #1, %0\n\t" + : "=r" (__dest), "=r" (__src), "=&z" (__dummy) + : "0" (__dest), "1" (__src) + : "memory", "t"); + + return __xdest; +} + +#define __HAVE_ARCH_STRNCPY +static inline char *strncpy(char *__dest, const char *__src, size_t __n) +{ + register char *__xdest = __dest; + unsigned long __dummy; + + if (__n == 0) + return __xdest; + + __asm__ __volatile__( + "1:\n" + "mov.b @%1+, %2\n\t" + "mov.b %2, @%0\n\t" + "cmp/eq #0, %2\n\t" + "bt/s 2f\n\t" + " cmp/eq %5,%1\n\t" + "bf/s 1b\n\t" + " add #1, %0\n" + "2:" + : "=r" (__dest), "=r" (__src), "=&z" (__dummy) + : "0" (__dest), "1" (__src), "r" (__src+__n) + : "memory", "t"); + + return __xdest; +} + +#define __HAVE_ARCH_STRCMP +static inline int strcmp(const char *__cs, const char *__ct) +{ + register int __res; + unsigned long __dummy; + + __asm__ __volatile__( + "mov.b @%1+, %3\n" + "1:\n\t" + "mov.b @%0+, %2\n\t" + "cmp/eq #0, %3\n\t" + "bt 2f\n\t" + "cmp/eq %2, %3\n\t" + "bt/s 1b\n\t" + " mov.b @%1+, %3\n\t" + "add #-2, %1\n\t" + "mov.b @%1, %3\n\t" + "sub %3, %2\n" + "2:" + : "=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy) + : "0" (__cs), "1" (__ct) + : "t"); + + return __res; +} + +#define __HAVE_ARCH_STRNCMP +static inline int strncmp(const char *__cs, const char *__ct, size_t __n) +{ + register int __res; + unsigned long __dummy; + + if (__n == 0) + return 0; + + __asm__ __volatile__( + "mov.b @%1+, %3\n" + "1:\n\t" + "mov.b @%0+, %2\n\t" + "cmp/eq %6, %0\n\t" + "bt/s 2f\n\t" + " cmp/eq #0, %3\n\t" + "bt/s 3f\n\t" + " cmp/eq %3, %2\n\t" + "bt/s 1b\n\t" + " mov.b @%1+, %3\n\t" + "add #-2, %1\n\t" + "mov.b @%1, %3\n" + "2:\n\t" + "sub %3, %2\n" + "3:" + :"=r" (__cs), "=r" (__ct), "=&r" (__res), "=&z" (__dummy) + : "0" (__cs), "1" (__ct), "r" (__cs+__n) + : "t"); + + return __res; +} + +#define __HAVE_ARCH_MEMSET +extern void *memset(void *__s, int __c, size_t __count); + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *__to, __const__ void *__from, size_t __n); + +#define __HAVE_ARCH_MEMMOVE +extern void *memmove(void *__dest, __const__ void *__src, size_t __n); + +#define __HAVE_ARCH_MEMCHR +extern void *memchr(const void *__s, int __c, size_t __n); + +#define __HAVE_ARCH_STRLEN +extern size_t strlen(const char *); + +#endif /* __KERNEL__ */ + +#endif /* __ASM_SH_STRING_H */ diff -puN /dev/null include/asm-sh/string_64.h --- /dev/null +++ a/include/asm-sh/string_64.h @@ -0,0 +1,17 @@ +#ifndef __ASM_SH_STRING_64_H +#define __ASM_SH_STRING_64_H + +/* + * include/asm-sh/string_64.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#define __HAVE_ARCH_MEMCPY +extern void *memcpy(void *dest, const void *src, size_t count); + +#endif /* __ASM_SH_STRING_64_H */ diff -puN include/asm-sh/system.h~git-sh include/asm-sh/system.h --- a/include/asm-sh/system.h~git-sh +++ a/include/asm-sh/system.h @@ -12,60 +12,9 @@ #include #include -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *next); +#define AT_VECTOR_SIZE_ARCH 5 /* entries in ARCH_DLINFO */ -#define AT_VECTOR_SIZE_ARCH 1 /* entries in ARCH_DLINFO */ -/* - * switch_to() should switch tasks to task nr n, first - */ - -#define switch_to(prev, next, last) do { \ - struct task_struct *__last; \ - register unsigned long *__ts1 __asm__ ("r1") = &prev->thread.sp; \ - register unsigned long *__ts2 __asm__ ("r2") = &prev->thread.pc; \ - register unsigned long *__ts4 __asm__ ("r4") = (unsigned long *)prev; \ - register unsigned long *__ts5 __asm__ ("r5") = (unsigned long *)next; \ - register unsigned long *__ts6 __asm__ ("r6") = &next->thread.sp; \ - register unsigned long __ts7 __asm__ ("r7") = next->thread.pc; \ - __asm__ __volatile__ (".balign 4\n\t" \ - "stc.l gbr, @-r15\n\t" \ - "sts.l pr, @-r15\n\t" \ - "mov.l r8, @-r15\n\t" \ - "mov.l r9, @-r15\n\t" \ - "mov.l r10, @-r15\n\t" \ - "mov.l r11, @-r15\n\t" \ - "mov.l r12, @-r15\n\t" \ - "mov.l r13, @-r15\n\t" \ - "mov.l r14, @-r15\n\t" \ - "mov.l r15, @r1 ! save SP\n\t" \ - "mov.l @r6, r15 ! change to new stack\n\t" \ - "mova 1f, %0\n\t" \ - "mov.l %0, @r2 ! save PC\n\t" \ - "mov.l 2f, %0\n\t" \ - "jmp @%0 ! call __switch_to\n\t" \ - " lds r7, pr ! with return to new PC\n\t" \ - ".balign 4\n" \ - "2:\n\t" \ - ".long __switch_to\n" \ - "1:\n\t" \ - "mov.l @r15+, r14\n\t" \ - "mov.l @r15+, r13\n\t" \ - "mov.l @r15+, r12\n\t" \ - "mov.l @r15+, r11\n\t" \ - "mov.l @r15+, r10\n\t" \ - "mov.l @r15+, r9\n\t" \ - "mov.l @r15+, r8\n\t" \ - "lds.l @r15+, pr\n\t" \ - "ldc.l @r15+, gbr\n\t" \ - : "=z" (__last) \ - : "r" (__ts1), "r" (__ts2), "r" (__ts4), \ - "r" (__ts5), "r" (__ts6), "r" (__ts7) \ - : "r3", "t"); \ - last = __last; \ -} while (0) - -#ifdef CONFIG_CPU_SH4A +#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5) #define __icbi() \ { \ unsigned long __addr; \ @@ -91,7 +40,7 @@ struct task_struct *__switch_to(struct t * Historically we have only done this type of barrier for the MMUCR, but * it's also necessary for the CCR, so we make it generic here instead. */ -#ifdef CONFIG_CPU_SH4A +#if defined(CONFIG_CPU_SH4A) || defined(CONFIG_CPU_SH5) #define mb() __asm__ __volatile__ ("synco": : :"memory") #define rmb() mb() #define wmb() __asm__ __volatile__ ("synco": : :"memory") @@ -119,63 +68,11 @@ struct task_struct *__switch_to(struct t #define set_mb(var, value) do { (void)xchg(&var, value); } while (0) -/* - * Jump to P2 area. - * When handling TLB or caches, we need to do it from P2 area. - */ -#define jump_to_P2() \ -do { \ - unsigned long __dummy; \ - __asm__ __volatile__( \ - "mov.l 1f, %0\n\t" \ - "or %1, %0\n\t" \ - "jmp @%0\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "1: .long 2f\n" \ - "2:" \ - : "=&r" (__dummy) \ - : "r" (0x20000000)); \ -} while (0) - -/* - * Back to P1 area. - */ -#define back_to_P1() \ -do { \ - unsigned long __dummy; \ - ctrl_barrier(); \ - __asm__ __volatile__( \ - "mov.l 1f, %0\n\t" \ - "jmp @%0\n\t" \ - " nop\n\t" \ - ".balign 4\n" \ - "1: .long 2f\n" \ - "2:" \ - : "=&r" (__dummy)); \ -} while (0) - -static inline unsigned long xchg_u32(volatile u32 *m, unsigned long val) -{ - unsigned long flags, retval; - - local_irq_save(flags); - retval = *m; - *m = val; - local_irq_restore(flags); - return retval; -} - -static inline unsigned long xchg_u8(volatile u8 *m, unsigned long val) -{ - unsigned long flags, retval; - - local_irq_save(flags); - retval = *m; - *m = val & 0xff; - local_irq_restore(flags); - return retval; -} +#ifdef CONFIG_GUSA_RB +#include +#else +#include +#endif extern void __xchg_called_with_bad_pointer(void); @@ -202,20 +99,6 @@ extern void __xchg_called_with_bad_point #define xchg(ptr,x) \ ((__typeof__(*(ptr)))__xchg((ptr),(unsigned long)(x), sizeof(*(ptr)))) -static inline unsigned long __cmpxchg_u32(volatile int * m, unsigned long old, - unsigned long new) -{ - __u32 retval; - unsigned long flags; - - local_irq_save(flags); - retval = *m; - if (retval == old) - *m = new; - local_irq_restore(flags); /* implies memory barrier */ - return retval; -} - /* This function doesn't exist, so you'll get a linker error * if something tries to do an invalid cmpxchg(). */ extern void __cmpxchg_called_with_bad_pointer(void); @@ -255,10 +138,14 @@ static inline void *set_exception_table_ */ #ifdef CONFIG_CPU_SH2A extern unsigned int instruction_size(unsigned int insn); -#else +#elif defined(CONFIG_SUPERH32) #define instruction_size(insn) (2) +#else +#define instruction_size(insn) (4) #endif +extern unsigned long cached_to_uncached; + /* XXX * disable hlt during certain critical i/o operations */ @@ -270,13 +157,35 @@ void default_idle(void); void per_cpu_trap_init(void); asmlinkage void break_point_trap(void); -asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs); -asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7, - struct pt_regs __regs); + +#ifdef CONFIG_SUPERH32 +#define BUILD_TRAP_HANDLER(name) \ +asmlinkage void name##_trap_handler(unsigned long r4, unsigned long r5, \ + unsigned long r6, unsigned long r7, \ + struct pt_regs __regs) + +#define TRAP_HANDLER_DECL \ + struct pt_regs *regs = RELOC_HIDE(&__regs, 0); \ + unsigned int vec = regs->tra; \ + (void)vec; +#else +#define BUILD_TRAP_HANDLER(name) \ +asmlinkage void name##_trap_handler(unsigned int vec, struct pt_regs *regs) +#define TRAP_HANDLER_DECL +#endif + +BUILD_TRAP_HANDLER(address_error); +BUILD_TRAP_HANDLER(debug); +BUILD_TRAP_HANDLER(bug); +BUILD_TRAP_HANDLER(fpu_error); +BUILD_TRAP_HANDLER(fpu_state_restore); #define arch_align_stack(x) (x) +#ifdef CONFIG_SUPERH32 +# include "system_32.h" +#else +# include "system_64.h" +#endif + #endif diff -puN /dev/null include/asm-sh/system_32.h --- /dev/null +++ a/include/asm-sh/system_32.h @@ -0,0 +1,99 @@ +#ifndef __ASM_SH_SYSTEM_32_H +#define __ASM_SH_SYSTEM_32_H + +#include + +struct task_struct *__switch_to(struct task_struct *prev, + struct task_struct *next); + +/* + * switch_to() should switch tasks to task nr n, first + */ +#define switch_to(prev, next, last) \ +do { \ + register u32 *__ts1 __asm__ ("r1") = (u32 *)&prev->thread.sp; \ + register u32 *__ts2 __asm__ ("r2") = (u32 *)&prev->thread.pc; \ + register u32 *__ts4 __asm__ ("r4") = (u32 *)prev; \ + register u32 *__ts5 __asm__ ("r5") = (u32 *)next; \ + register u32 *__ts6 __asm__ ("r6") = (u32 *)&next->thread.sp; \ + register u32 __ts7 __asm__ ("r7") = next->thread.pc; \ + struct task_struct *__last; \ + \ + __asm__ __volatile__ ( \ + ".balign 4\n\t" \ + "stc.l gbr, @-r15\n\t" \ + "sts.l pr, @-r15\n\t" \ + "mov.l r8, @-r15\n\t" \ + "mov.l r9, @-r15\n\t" \ + "mov.l r10, @-r15\n\t" \ + "mov.l r11, @-r15\n\t" \ + "mov.l r12, @-r15\n\t" \ + "mov.l r13, @-r15\n\t" \ + "mov.l r14, @-r15\n\t" \ + "mov.l r15, @r1\t! save SP\n\t" \ + "mov.l @r6, r15\t! change to new stack\n\t" \ + "mova 1f, %0\n\t" \ + "mov.l %0, @r2\t! save PC\n\t" \ + "mov.l 2f, %0\n\t" \ + "jmp @%0\t! call __switch_to\n\t" \ + " lds r7, pr\t! with return to new PC\n\t" \ + ".balign 4\n" \ + "2:\n\t" \ + ".long __switch_to\n" \ + "1:\n\t" \ + "mov.l @r15+, r14\n\t" \ + "mov.l @r15+, r13\n\t" \ + "mov.l @r15+, r12\n\t" \ + "mov.l @r15+, r11\n\t" \ + "mov.l @r15+, r10\n\t" \ + "mov.l @r15+, r9\n\t" \ + "mov.l @r15+, r8\n\t" \ + "lds.l @r15+, pr\n\t" \ + "ldc.l @r15+, gbr\n\t" \ + : "=z" (__last) \ + : "r" (__ts1), "r" (__ts2), "r" (__ts4), \ + "r" (__ts5), "r" (__ts6), "r" (__ts7) \ + : "r3", "t"); \ + \ + last = __last; \ +} while (0) + +#define __uses_jump_to_uncached __attribute__ ((__section__ (".uncached.text"))) + +/* + * Jump to uncached area. + * When handling TLB or caches, we need to do it from an uncached area. + */ +#define jump_to_uncached() \ +do { \ + unsigned long __dummy; \ + \ + __asm__ __volatile__( \ + "mova 1f, %0\n\t" \ + "add %1, %0\n\t" \ + "jmp @%0\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "1:" \ + : "=&z" (__dummy) \ + : "r" (cached_to_uncached)); \ +} while (0) + +/* + * Back to cached area. + */ +#define back_to_cached() \ +do { \ + unsigned long __dummy; \ + ctrl_barrier(); \ + __asm__ __volatile__( \ + "mov.l 1f, %0\n\t" \ + "jmp @%0\n\t" \ + " nop\n\t" \ + ".balign 4\n" \ + "1: .long 2f\n" \ + "2:" \ + : "=&r" (__dummy)); \ +} while (0) + +#endif /* __ASM_SH_SYSTEM_32_H */ diff -puN /dev/null include/asm-sh/system_64.h --- /dev/null +++ a/include/asm-sh/system_64.h @@ -0,0 +1,40 @@ +#ifndef __ASM_SH_SYSTEM_64_H +#define __ASM_SH_SYSTEM_64_H + +/* + * include/asm-sh/system_64.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 Paul Mundt + * Copyright (C) 2004 Richard Curnow + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include + +/* + * switch_to() should switch tasks to task nr n, first + */ +struct task_struct *sh64_switch_to(struct task_struct *prev, + struct thread_struct *prev_thread, + struct task_struct *next, + struct thread_struct *next_thread); + +#define switch_to(prev,next,last) \ +do { \ + if (last_task_used_math != next) { \ + struct pt_regs *regs = next->thread.uregs; \ + if (regs) regs->sr |= SR_FD; \ + } \ + last = sh64_switch_to(prev, &prev->thread, next, \ + &next->thread); \ +} while (0) + +#define __uses_jump_to_uncached + +#define jump_to_uncached() do { } while (0) +#define back_to_cached() do { } while (0) + +#endif /* __ASM_SH_SYSTEM_64_H */ diff -puN include/asm-sh/thread_info.h~git-sh include/asm-sh/thread_info.h --- a/include/asm-sh/thread_info.h~git-sh +++ a/include/asm-sh/thread_info.h @@ -74,8 +74,10 @@ register unsigned long current_stack_poi static inline struct thread_info *current_thread_info(void) { struct thread_info *ti; -#ifdef CONFIG_CPU_HAS_SR_RB - __asm__("stc r7_bank, %0" : "=r" (ti)); +#if defined(CONFIG_SUPERH64) + __asm__ __volatile__ ("getcon cr17, %0" : "=r" (ti)); +#elif defined(CONFIG_CPU_HAS_SR_RB) + __asm__ __volatile__ ("stc r7_bank, %0" : "=r" (ti)); #else unsigned long __dummy; @@ -111,6 +113,7 @@ static inline struct thread_info *curren #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_RESTORE_SIGMASK 3 /* restore signal mask in do_signal() */ #define TIF_SINGLESTEP 4 /* singlestepping active */ +#define TIF_SYSCALL_AUDIT 5 #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_MEMDIE 18 @@ -121,6 +124,7 @@ static inline struct thread_info *curren #define _TIF_NEED_RESCHED (1<vm_start, vma->vm_end) @@ -15,4 +21,6 @@ #define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) #include -#endif + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_SH_TLB_H */ diff -puN /dev/null include/asm-sh/tlb_64.h --- /dev/null +++ a/include/asm-sh/tlb_64.h @@ -0,0 +1,69 @@ +/* + * include/asm-sh/tlb_64.h + * + * Copyright (C) 2003 Paul Mundt + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#ifndef __ASM_SH_TLB_64_H +#define __ASM_SH_TLB_64_H + +/* ITLB defines */ +#define ITLB_FIXED 0x00000000 /* First fixed ITLB, see head.S */ +#define ITLB_LAST_VAR_UNRESTRICTED 0x000003F0 /* Last ITLB */ + +/* DTLB defines */ +#define DTLB_FIXED 0x00800000 /* First fixed DTLB, see head.S */ +#define DTLB_LAST_VAR_UNRESTRICTED 0x008003F0 /* Last DTLB */ + +#ifndef __ASSEMBLY__ + +/** + * for_each_dtlb_entry + * + * @tlb: TLB entry + * + * Iterate over free (non-wired) DTLB entries + */ +#define for_each_dtlb_entry(tlb) \ + for (tlb = cpu_data->dtlb.first; \ + tlb <= cpu_data->dtlb.last; \ + tlb += cpu_data->dtlb.step) + +/** + * for_each_itlb_entry + * + * @tlb: TLB entry + * + * Iterate over free (non-wired) ITLB entries + */ +#define for_each_itlb_entry(tlb) \ + for (tlb = cpu_data->itlb.first; \ + tlb <= cpu_data->itlb.last; \ + tlb += cpu_data->itlb.step) + +/** + * __flush_tlb_slot + * + * @slot: Address of TLB slot. + * + * Flushes TLB slot @slot. + */ +static inline void __flush_tlb_slot(unsigned long long slot) +{ + __asm__ __volatile__ ("putcfg %0, 0, r63\n" : : "r" (slot)); +} + +/* arch/sh64/mm/tlb.c */ +int sh64_tlb_init(void); +unsigned long long sh64_next_free_dtlb_entry(void); +unsigned long long sh64_get_wired_dtlb_entry(void); +int sh64_put_wired_dtlb_entry(unsigned long long entry); +void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr, + unsigned long asid, unsigned long paddr); +void sh64_teardown_tlb_slot(unsigned long long config_addr); + +#endif /* __ASSEMBLY__ */ +#endif /* __ASM_SH_TLB_64_H */ diff -puN include/asm-sh/types.h~git-sh include/asm-sh/types.h --- a/include/asm-sh/types.h~git-sh +++ a/include/asm-sh/types.h @@ -52,6 +52,12 @@ typedef unsigned long long u64; typedef u32 dma_addr_t; +#ifdef CONFIG_SUPERH32 +typedef u16 opcode_t; +#else +typedef u32 opcode_t; +#endif + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ diff -puN include/asm-sh/uaccess.h~git-sh include/asm-sh/uaccess.h --- a/include/asm-sh/uaccess.h~git-sh +++ a/include/asm-sh/uaccess.h @@ -1,575 +1,5 @@ -/* $Id: uaccess.h,v 1.11 2003/10/13 07:21:20 lethal Exp $ - * - * User space memory access functions - * - * Copyright (C) 1999, 2002 Niibe Yutaka - * Copyright (C) 2003 Paul Mundt - * - * Based on: - * MIPS implementation version 1.15 by - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle - * and i386 version. - */ -#ifndef __ASM_SH_UACCESS_H -#define __ASM_SH_UACCESS_H - -#include -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons (Data Segment Register?), these macros are misnamed. - */ - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) - -#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL) -#define USER_DS MAKE_MM_SEG(PAGE_OFFSET) - -#define segment_eq(a,b) ((a).seg == (b).seg) - -#define get_ds() (KERNEL_DS) - -#if !defined(CONFIG_MMU) -/* NOMMU is always true */ -#define __addr_ok(addr) (1) - -static inline mm_segment_t get_fs(void) -{ - return USER_DS; -} - -static inline void set_fs(mm_segment_t s) -{ -} - -/* - * __access_ok: Check if address with size is OK or not. - * - * If we don't have an MMU (or if its disabled) the only thing we really have - * to look out for is if the address resides somewhere outside of what - * available RAM we have. - * - * TODO: This check could probably also stand to be restricted somewhat more.. - * though it still does the Right Thing(tm) for the time being. - */ -static inline int __access_ok(unsigned long addr, unsigned long size) -{ - return ((addr >= memory_start) && ((addr + size) < memory_end)); -} -#else /* CONFIG_MMU */ -#define __addr_ok(addr) \ - ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) - -#define get_fs() (current_thread_info()->addr_limit) -#define set_fs(x) (current_thread_info()->addr_limit = (x)) - -/* - * __access_ok: Check if address with size is OK or not. - * - * We do three checks: - * (1) is it user space? - * (2) addr + size --> carry? - * (3) addr + size >= 0x80000000 (PAGE_OFFSET) - * - * (1) (2) (3) | RESULT - * 0 0 0 | ok - * 0 0 1 | ok - * 0 1 0 | bad - * 0 1 1 | bad - * 1 0 0 | ok - * 1 0 1 | bad - * 1 1 0 | bad - * 1 1 1 | bad - */ -static inline int __access_ok(unsigned long addr, unsigned long size) -{ - unsigned long flag, tmp; - - __asm__("stc r7_bank, %0\n\t" - "mov.l @(8,%0), %0\n\t" - "clrt\n\t" - "addc %2, %1\n\t" - "and %1, %0\n\t" - "rotcl %0\n\t" - "rotcl %0\n\t" - "and #3, %0" - : "=&z" (flag), "=r" (tmp) - : "r" (addr), "1" (size) - : "t"); - - return flag == 0; -} -#endif /* CONFIG_MMU */ - -static inline int access_ok(int type, const void __user *p, unsigned long size) -{ - unsigned long addr = (unsigned long)p; - return __access_ok(addr, size); -} - -/* - * Uh, these should become the main single-value transfer routines ... - * They automatically use the right size if we just have the right - * pointer type ... - * - * As SuperH uses the same address space for kernel and user data, we - * can just do these as direct assignments. - * - * Careful to not - * (a) re-use the arguments for side effects (sizeof is ok) - * (b) require any knowledge of processes at this stage - */ -#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) -#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) - -/* - * The "__xxx" versions do not do address space checking, useful when - * doing multiple accesses to the same area (the user has to do the - * checks by hand with "access_ok()") - */ -#define __put_user(x,ptr) \ - __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) \ - __get_user_nocheck((x),(ptr),sizeof(*(ptr))) - -struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct __user *)(x)) - -#define __get_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - __chk_user_ptr(ptr); \ - switch (size) { \ - case 1: \ - __get_user_asm(x, ptr, retval, "b"); \ - break; \ - case 2: \ - __get_user_asm(x, ptr, retval, "w"); \ - break; \ - case 4: \ - __get_user_asm(x, ptr, retval, "l"); \ - break; \ - default: \ - __get_user_unknown(); \ - break; \ - } \ -} while (0) - -#define __get_user_nocheck(x,ptr,size) \ -({ \ - long __gu_err, __gu_val; \ - __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#ifdef CONFIG_MMU -#define __get_user_check(x,ptr,size) \ -({ \ - long __gu_err, __gu_val; \ - __chk_user_ptr(ptr); \ - switch (size) { \ - case 1: \ - __get_user_1(__gu_val, (ptr), __gu_err); \ - break; \ - case 2: \ - __get_user_2(__gu_val, (ptr), __gu_err); \ - break; \ - case 4: \ - __get_user_4(__gu_val, (ptr), __gu_err); \ - break; \ - default: \ - __get_user_unknown(); \ - break; \ - } \ - \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_1(x,addr,err) ({ \ -__asm__("stc r7_bank, %1\n\t" \ - "mov.l @(8,%1), %1\n\t" \ - "and %2, %1\n\t" \ - "cmp/pz %1\n\t" \ - "bt/s 1f\n\t" \ - " mov #0, %0\n\t" \ - "0:\n" \ - "mov #-14, %0\n\t" \ - "bra 2f\n\t" \ - " mov #0, %1\n" \ - "1:\n\t" \ - "mov.b @%2, %1\n\t" \ - "extu.b %1, %1\n" \ - "2:\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 0b\n\t" \ - ".previous" \ - : "=&r" (err), "=&r" (x) \ - : "r" (addr) \ - : "t"); \ -}) - -#define __get_user_2(x,addr,err) ({ \ -__asm__("stc r7_bank, %1\n\t" \ - "mov.l @(8,%1), %1\n\t" \ - "and %2, %1\n\t" \ - "cmp/pz %1\n\t" \ - "bt/s 1f\n\t" \ - " mov #0, %0\n\t" \ - "0:\n" \ - "mov #-14, %0\n\t" \ - "bra 2f\n\t" \ - " mov #0, %1\n" \ - "1:\n\t" \ - "mov.w @%2, %1\n\t" \ - "extu.w %1, %1\n" \ - "2:\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 0b\n\t" \ - ".previous" \ - : "=&r" (err), "=&r" (x) \ - : "r" (addr) \ - : "t"); \ -}) - -#define __get_user_4(x,addr,err) ({ \ -__asm__("stc r7_bank, %1\n\t" \ - "mov.l @(8,%1), %1\n\t" \ - "and %2, %1\n\t" \ - "cmp/pz %1\n\t" \ - "bt/s 1f\n\t" \ - " mov #0, %0\n\t" \ - "0:\n" \ - "mov #-14, %0\n\t" \ - "bra 2f\n\t" \ - " mov #0, %1\n" \ - "1:\n\t" \ - "mov.l @%2, %1\n\t" \ - "2:\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 0b\n\t" \ - ".previous" \ - : "=&r" (err), "=&r" (x) \ - : "r" (addr) \ - : "t"); \ -}) -#else /* CONFIG_MMU */ -#define __get_user_check(x,ptr,size) \ -({ \ - long __gu_err, __gu_val; \ - if (__access_ok((unsigned long)(ptr), (size))) { \ - __get_user_size(__gu_val, (ptr), (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - } else \ - __gu_err = -EFAULT; \ - __gu_err; \ -}) -#endif - -#define __get_user_asm(x, addr, err, insn) \ -({ \ -__asm__ __volatile__( \ - "1:\n\t" \ - "mov." insn " %2, %1\n\t" \ - "mov #0, %0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3:\n\t" \ - "mov #0, %1\n\t" \ - "mov.l 4f, %0\n\t" \ - "jmp @%0\n\t" \ - " mov %3, %0\n" \ - "4: .long 2b\n\t" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 3b\n\t" \ - ".previous" \ - :"=&r" (err), "=&r" (x) \ - :"m" (__m(addr)), "i" (-EFAULT)); }) - -extern void __get_user_unknown(void); - -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - __chk_user_ptr(ptr); \ - switch (size) { \ - case 1: \ - __put_user_asm(x, ptr, retval, "b"); \ - break; \ - case 2: \ - __put_user_asm(x, ptr, retval, "w"); \ - break; \ - case 4: \ - __put_user_asm(x, ptr, retval, "l"); \ - break; \ - case 8: \ - __put_user_u64(x, ptr, retval); \ - break; \ - default: \ - __put_user_unknown(); \ - } \ -} while (0) - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err; \ - __put_user_size((x),(ptr),(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ - \ - if (__access_ok((unsigned long)__pu_addr,size)) \ - __put_user_size((x),__pu_addr,(size),__pu_err); \ - __pu_err; \ -}) - -#define __put_user_asm(x, addr, err, insn) \ -({ \ -__asm__ __volatile__( \ - "1:\n\t" \ - "mov." insn " %1, %2\n\t" \ - "mov #0, %0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3:\n\t" \ - "nop\n\t" \ - "mov.l 4f, %0\n\t" \ - "jmp @%0\n\t" \ - "mov %3, %0\n" \ - "4: .long 2b\n\t" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 3b\n\t" \ - ".previous" \ - :"=&r" (err) \ - :"r" (x), "m" (__m(addr)), "i" (-EFAULT) \ - :"memory"); }) - -#if defined(__LITTLE_ENDIAN__) -#define __put_user_u64(val,addr,retval) \ -({ \ -__asm__ __volatile__( \ - "1:\n\t" \ - "mov.l %R1,%2\n\t" \ - "mov.l %S1,%T2\n\t" \ - "mov #0,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3:\n\t" \ - "nop\n\t" \ - "mov.l 4f,%0\n\t" \ - "jmp @%0\n\t" \ - " mov %3,%0\n" \ - "4: .long 2b\n\t" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 3b\n\t" \ - ".previous" \ - : "=r" (retval) \ - : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \ - : "memory"); }) +#ifdef CONFIG_SUPERH32 +# include "uaccess_32.h" #else -#define __put_user_u64(val,addr,retval) \ -({ \ -__asm__ __volatile__( \ - "1:\n\t" \ - "mov.l %S1,%2\n\t" \ - "mov.l %R1,%T2\n\t" \ - "mov #0,%0\n" \ - "2:\n" \ - ".section .fixup,\"ax\"\n" \ - "3:\n\t" \ - "nop\n\t" \ - "mov.l 4f,%0\n\t" \ - "jmp @%0\n\t" \ - " mov %3,%0\n" \ - "4: .long 2b\n\t" \ - ".previous\n" \ - ".section __ex_table,\"a\"\n\t" \ - ".long 1b, 3b\n\t" \ - ".previous" \ - : "=r" (retval) \ - : "r" (val), "m" (__m(addr)), "i" (-EFAULT) \ - : "memory"); }) +# include "uaccess_64.h" #endif - -extern void __put_user_unknown(void); - -/* Generic arbitrary sized copy. */ -/* Return the number of bytes NOT copied */ -__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); - -#define copy_to_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - -#define copy_from_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -void *__copy_from = (void *) (from); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - -static __always_inline unsigned long -__copy_from_user(void *to, const void __user *from, unsigned long n) -{ - return __copy_user(to, (__force void *)from, n); -} - -static __always_inline unsigned long __must_check -__copy_to_user(void __user *to, const void *from, unsigned long n) -{ - return __copy_user((__force void *)to, from, n); -} - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -/* - * Clear the area and return remaining number of bytes - * (on failure. Usually it's 0.) - */ -extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size); - -#define clear_user(addr,n) ({ \ -void * __cl_addr = (addr); \ -unsigned long __cl_size = (n); \ -if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \ -__cl_size = __clear_user(__cl_addr, __cl_size); \ -__cl_size; }) - -static __inline__ int -__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) -{ - __kernel_size_t res; - unsigned long __dummy, _d, _s; - - __asm__ __volatile__( - "9:\n" - "mov.b @%2+, %1\n\t" - "cmp/eq #0, %1\n\t" - "bt/s 2f\n" - "1:\n" - "mov.b %1, @%3\n\t" - "dt %7\n\t" - "bf/s 9b\n\t" - " add #1, %3\n\t" - "2:\n\t" - "sub %7, %0\n" - "3:\n" - ".section .fixup,\"ax\"\n" - "4:\n\t" - "mov.l 5f, %1\n\t" - "jmp @%1\n\t" - " mov %8, %0\n\t" - ".balign 4\n" - "5: .long 3b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .balign 4\n" - " .long 9b,4b\n" - ".previous" - : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d) - : "0" (__count), "2" (__src), "3" (__dest), "r" (__count), - "i" (-EFAULT) - : "memory", "t"); - - return res; -} - -#define strncpy_from_user(dest,src,count) ({ \ -unsigned long __sfu_src = (unsigned long) (src); \ -int __sfu_count = (int) (count); \ -long __sfu_res = -EFAULT; \ -if(__access_ok(__sfu_src, __sfu_count)) { \ -__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ -} __sfu_res; }) - -/* - * Return the size of a string (including the ending 0!) - */ -static __inline__ long __strnlen_user(const char __user *__s, long __n) -{ - unsigned long res; - unsigned long __dummy; - - __asm__ __volatile__( - "9:\n" - "cmp/eq %4, %0\n\t" - "bt 2f\n" - "1:\t" - "mov.b @(%0,%3), %1\n\t" - "tst %1, %1\n\t" - "bf/s 9b\n\t" - " add #1, %0\n" - "2:\n" - ".section .fixup,\"ax\"\n" - "3:\n\t" - "mov.l 4f, %1\n\t" - "jmp @%1\n\t" - " mov #0, %0\n" - ".balign 4\n" - "4: .long 2b\n" - ".previous\n" - ".section __ex_table,\"a\"\n" - " .balign 4\n" - " .long 1b,3b\n" - ".previous" - : "=z" (res), "=&r" (__dummy) - : "0" (0), "r" (__s), "r" (__n) - : "t"); - return res; -} - -static __inline__ long strnlen_user(const char __user *s, long n) -{ - if (!__addr_ok(s)) - return 0; - else - return __strnlen_user(s, n); -} - -#define strlen_user(str) strnlen_user(str, ~0UL >> 1) - -/* - * 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; -}; - -extern int fixup_exception(struct pt_regs *regs); - -#endif /* __ASM_SH_UACCESS_H */ diff -puN /dev/null include/asm-sh/uaccess_32.h --- /dev/null +++ a/include/asm-sh/uaccess_32.h @@ -0,0 +1,518 @@ +/* $Id: uaccess.h,v 1.11 2003/10/13 07:21:20 lethal Exp $ + * + * User space memory access functions + * + * Copyright (C) 1999, 2002 Niibe Yutaka + * Copyright (C) 2003 Paul Mundt + * + * Based on: + * MIPS implementation version 1.15 by + * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * and i386 version. + */ +#ifndef __ASM_SH_UACCESS_H +#define __ASM_SH_UACCESS_H + +#include +#include + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons (Data Segment Register?), these macros are misnamed. + */ + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFFUL) +#define USER_DS MAKE_MM_SEG(PAGE_OFFSET) + +#define segment_eq(a,b) ((a).seg == (b).seg) + +#define get_ds() (KERNEL_DS) + +#if !defined(CONFIG_MMU) +/* NOMMU is always true */ +#define __addr_ok(addr) (1) + +static inline mm_segment_t get_fs(void) +{ + return USER_DS; +} + +static inline void set_fs(mm_segment_t s) +{ +} + +/* + * __access_ok: Check if address with size is OK or not. + * + * If we don't have an MMU (or if its disabled) the only thing we really have + * to look out for is if the address resides somewhere outside of what + * available RAM we have. + * + * TODO: This check could probably also stand to be restricted somewhat more.. + * though it still does the Right Thing(tm) for the time being. + */ +static inline int __access_ok(unsigned long addr, unsigned long size) +{ + return ((addr >= memory_start) && ((addr + size) < memory_end)); +} +#else /* CONFIG_MMU */ +#define __addr_ok(addr) \ + ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) + +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(x) (current_thread_info()->addr_limit = (x)) + +/* + * __access_ok: Check if address with size is OK or not. + * + * Uhhuh, this needs 33-bit arithmetic. We have a carry.. + * + * sum := addr + size; carry? --> flag = true; + * if (sum >= addr_limit) flag = true; + */ +static inline int __access_ok(unsigned long addr, unsigned long size) +{ + unsigned long flag, sum; + + __asm__("clrt\n\t" + "addc %3, %1\n\t" + "movt %0\n\t" + "cmp/hi %4, %1\n\t" + "rotcl %0" + :"=&r" (flag), "=r" (sum) + :"1" (addr), "r" (size), + "r" (current_thread_info()->addr_limit.seg) + :"t"); + return flag == 0; +} +#endif /* CONFIG_MMU */ + +static inline int access_ok(int type, const void __user *p, unsigned long size) +{ + unsigned long addr = (unsigned long)p; + return __access_ok(addr, size); +} + +/* + * Uh, these should become the main single-value transfer routines ... + * They automatically use the right size if we just have the right + * pointer type ... + * + * As SuperH uses the same address space for kernel and user data, we + * can just do these as direct assignments. + * + * Careful to not + * (a) re-use the arguments for side effects (sizeof is ok) + * (b) require any knowledge of processes at this stage + */ +#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) +#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) + +/* + * The "__xxx" versions do not do address space checking, useful when + * doing multiple accesses to the same area (the user has to do the + * checks by hand with "access_ok()") + */ +#define __put_user(x,ptr) \ + __put_user_nocheck((__typeof__(*(ptr)))(x),(ptr),sizeof(*(ptr))) +#define __get_user(x,ptr) \ + __get_user_nocheck((x),(ptr),sizeof(*(ptr))) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct __user *)(x)) + +#define __get_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: \ + __get_user_asm(x, ptr, retval, "b"); \ + break; \ + case 2: \ + __get_user_asm(x, ptr, retval, "w"); \ + break; \ + case 4: \ + __get_user_asm(x, ptr, retval, "l"); \ + break; \ + default: \ + __get_user_unknown(); \ + break; \ + } \ +} while (0) + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + __get_user_size(__gu_val, (__pu_addr), (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __get_user_check(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + __typeof__(*(ptr)) *__pu_addr = (ptr); \ + __chk_user_ptr(__pu_addr); \ + if (likely(__addr_ok((unsigned long)(__pu_addr)))) { \ + __get_user_size(__gu_val, (__pu_addr), (size), __gu_err);\ + } else { \ + __gu_err = -EFAULT; \ + __gu_val = 0; \ + } \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __get_user_asm(x, addr, err, insn) \ +({ \ +__asm__ __volatile__( \ + "1:\n\t" \ + "mov." insn " %2, %1\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3:\n\t" \ + "mov #0, %1\n\t" \ + "mov.l 4f, %0\n\t" \ + "jmp @%0\n\t" \ + " mov %3, %0\n\t" \ + ".balign 4\n" \ + "4: .long 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n\t" \ + ".long 1b, 3b\n\t" \ + ".previous" \ + :"=&r" (err), "=&r" (x) \ + :"m" (__m(addr)), "i" (-EFAULT), "0" (err)); }) + +extern void __get_user_unknown(void); + +#define __put_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + __chk_user_ptr(ptr); \ + switch (size) { \ + case 1: \ + __put_user_asm(x, ptr, retval, "b"); \ + break; \ + case 2: \ + __put_user_asm(x, ptr, retval, "w"); \ + break; \ + case 4: \ + __put_user_asm(x, ptr, retval, "l"); \ + break; \ + case 8: \ + __put_user_u64(x, ptr, retval); \ + break; \ + default: \ + __put_user_unknown(); \ + } \ +} while (0) + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err; \ + __put_user_size((x),(ptr),(size),__pu_err); \ + __pu_err; \ +}) + +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err; \ + __typeof__(*(ptr)) __user *__pu_addr = (ptr); \ + \ + if (likely(__addr_ok((unsigned long)__pu_addr))) \ + __put_user_size((x),__pu_addr,(size),__pu_err); \ + else \ + __pu_err = -EFAULT; \ + __pu_err; \ +}) + +#define __put_user_asm(x, addr, err, insn) \ +({ \ +__asm__ __volatile__( \ + "1:\n\t" \ + "mov." insn " %1, %2\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3:\n\t" \ + "mov.l 4f, %0\n\t" \ + "jmp @%0\n\t" \ + " mov %3, %0\n\t" \ + ".balign 4\n" \ + "4: .long 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n\t" \ + ".long 1b, 3b\n\t" \ + ".previous" \ + :"=&r" (err) \ + :"r" (x), "m" (__m(addr)), "i" (-EFAULT), "0" (err) \ + :"memory"); }) + +#if defined(CONFIG_CPU_LITTLE_ENDIAN) +#define __put_user_u64(val,addr,retval) \ +({ \ +__asm__ __volatile__( \ + "1:\n\t" \ + "mov.l %R1,%2\n\t" \ + "mov.l %S1,%T2\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3:\n\t" \ + "mov.l 4f,%0\n\t" \ + "jmp @%0\n\t" \ + " mov %3,%0\n\t" \ + ".balign 4\n" \ + "4: .long 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n\t" \ + ".long 1b, 3b\n\t" \ + ".previous" \ + : "=r" (retval) \ + : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \ + : "memory"); }) +#else +#define __put_user_u64(val,addr,retval) \ +({ \ +__asm__ __volatile__( \ + "1:\n\t" \ + "mov.l %S1,%2\n\t" \ + "mov.l %R1,%T2\n\t" \ + "2:\n" \ + ".section .fixup,\"ax\"\n" \ + "3:\n\t" \ + "mov.l 4f,%0\n\t" \ + "jmp @%0\n\t" \ + " mov %3,%0\n\t" \ + ".balign 4\n" \ + "4: .long 2b\n\t" \ + ".previous\n" \ + ".section __ex_table,\"a\"\n\t" \ + ".long 1b, 3b\n\t" \ + ".previous" \ + : "=r" (retval) \ + : "r" (val), "m" (__m(addr)), "i" (-EFAULT), "0" (retval) \ + : "memory"); }) +#endif + +extern void __put_user_unknown(void); + +/* Generic arbitrary sized copy. */ +/* Return the number of bytes NOT copied */ +__kernel_size_t __copy_user(void *to, const void *from, __kernel_size_t n); + +#define copy_to_user(to,from,n) ({ \ +void *__copy_to = (void *) (to); \ +__kernel_size_t __copy_size = (__kernel_size_t) (n); \ +__kernel_size_t __copy_res; \ +if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ +__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +#define copy_from_user(to,from,n) ({ \ +void *__copy_to = (void *) (to); \ +void *__copy_from = (void *) (from); \ +__kernel_size_t __copy_size = (__kernel_size_t) (n); \ +__kernel_size_t __copy_res; \ +if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ +__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +static __always_inline unsigned long +__copy_from_user(void *to, const void __user *from, unsigned long n) +{ + return __copy_user(to, (__force void *)from, n); +} + +static __always_inline unsigned long __must_check +__copy_to_user(void __user *to, const void *from, unsigned long n) +{ + return __copy_user((__force void *)to, from, n); +} + +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user + +/* + * Clear the area and return remaining number of bytes + * (on failure. Usually it's 0.) + */ +extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size); + +#define clear_user(addr,n) ({ \ +void * __cl_addr = (addr); \ +unsigned long __cl_size = (n); \ +if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \ +__cl_size = __clear_user(__cl_addr, __cl_size); \ +__cl_size; }) + +static __inline__ int +__strncpy_from_user(unsigned long __dest, unsigned long __user __src, int __count) +{ + __kernel_size_t res; + unsigned long __dummy, _d, _s, _c; + + __asm__ __volatile__( + "9:\n" + "mov.b @%2+, %1\n\t" + "cmp/eq #0, %1\n\t" + "bt/s 2f\n" + "1:\n" + "mov.b %1, @%3\n\t" + "dt %4\n\t" + "bf/s 9b\n\t" + " add #1, %3\n\t" + "2:\n\t" + "sub %4, %0\n" + "3:\n" + ".section .fixup,\"ax\"\n" + "4:\n\t" + "mov.l 5f, %1\n\t" + "jmp @%1\n\t" + " mov %9, %0\n\t" + ".balign 4\n" + "5: .long 3b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 9b,4b\n" + ".previous" + : "=r" (res), "=&z" (__dummy), "=r" (_s), "=r" (_d), "=r"(_c) + : "0" (__count), "2" (__src), "3" (__dest), "4" (__count), + "i" (-EFAULT) + : "memory", "t"); + + return res; +} + +/** + * strncpy_from_user: - Copy a NUL terminated string from userspace. + * @dst: Destination address, in kernel space. This buffer must be at + * least @count bytes long. + * @src: Source address, in user space. + * @count: Maximum number of bytes to copy, including the trailing NUL. + * + * Copies a NUL-terminated string from userspace to kernel space. + * + * On success, returns the length of the string (not including the trailing + * NUL). + * + * If access to userspace fails, returns -EFAULT (some data may have been + * copied). + * + * If @count is smaller than the length of the string, copies @count bytes + * and returns @count. + */ +#define strncpy_from_user(dest,src,count) ({ \ +unsigned long __sfu_src = (unsigned long) (src); \ +int __sfu_count = (int) (count); \ +long __sfu_res = -EFAULT; \ +if(__access_ok(__sfu_src, __sfu_count)) { \ +__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ +} __sfu_res; }) + +/* + * Return the size of a string (including the ending 0 even when we have + * exceeded the maximum string length). + */ +static __inline__ long __strnlen_user(const char __user *__s, long __n) +{ + unsigned long res; + unsigned long __dummy; + + __asm__ __volatile__( + "1:\t" + "mov.b @(%0,%3), %1\n\t" + "cmp/eq %4, %0\n\t" + "bt/s 2f\n\t" + " add #1, %0\n\t" + "tst %1, %1\n\t" + "bf 1b\n\t" + "2:\n" + ".section .fixup,\"ax\"\n" + "3:\n\t" + "mov.l 4f, %1\n\t" + "jmp @%1\n\t" + " mov #0, %0\n" + ".balign 4\n" + "4: .long 2b\n" + ".previous\n" + ".section __ex_table,\"a\"\n" + " .balign 4\n" + " .long 1b,3b\n" + ".previous" + : "=z" (res), "=&r" (__dummy) + : "0" (0), "r" (__s), "r" (__n) + : "t"); + return res; +} + +/** + * strnlen_user: - Get the size of a string in user space. + * @s: The string to measure. + * @n: The maximum valid length + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * If the string is too long, returns a value greater than @n. + */ +static __inline__ long strnlen_user(const char __user *s, long n) +{ + if (!__addr_ok(s)) + return 0; + else + return __strnlen_user(s, n); +} + +/** + * strlen_user: - Get the size of a string in user space. + * @str: The string to measure. + * + * Context: User context only. This function may sleep. + * + * Get the size of a NUL-terminated string in user space. + * + * Returns the size of the string INCLUDING the terminating NUL. + * On exception, returns 0. + * + * If there is a limit on the length of a valid string, you may wish to + * consider using strnlen_user() instead. + */ +#define strlen_user(str) strnlen_user(str, ~0UL >> 1) + +/* + * 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; +}; + +extern int fixup_exception(struct pt_regs *regs); + +#endif /* __ASM_SH_UACCESS_H */ diff -puN /dev/null include/asm-sh/uaccess_64.h --- /dev/null +++ a/include/asm-sh/uaccess_64.h @@ -0,0 +1,302 @@ +#ifndef __ASM_SH_UACCESS_64_H +#define __ASM_SH_UACCESS_64_H + +/* + * include/asm-sh/uaccess_64.h + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003, 2004 Paul Mundt + * + * User space memory access functions + * + * Copyright (C) 1999 Niibe Yutaka + * + * Based on: + * MIPS implementation version 1.15 by + * Copyright (C) 1996, 1997, 1998 by Ralf Baechle + * and i386 version. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#include +#include + +#define VERIFY_READ 0 +#define VERIFY_WRITE 1 + +/* + * The fs value determines whether argument validity checking should be + * performed or not. If get_fs() == USER_DS, checking is performed, with + * get_fs() == KERNEL_DS, checking is bypassed. + * + * For historical reasons (Data Segment Register?), these macros are misnamed. + */ + +#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) + +#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) +#define USER_DS MAKE_MM_SEG(0x80000000) + +#define get_ds() (KERNEL_DS) +#define get_fs() (current_thread_info()->addr_limit) +#define set_fs(x) (current_thread_info()->addr_limit=(x)) + +#define segment_eq(a,b) ((a).seg == (b).seg) + +#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) + +/* + * Uhhuh, this needs 33-bit arithmetic. We have a carry.. + * + * sum := addr + size; carry? --> flag = true; + * if (sum >= addr_limit) flag = true; + */ +#define __range_ok(addr,size) (((unsigned long) (addr) + (size) < (current_thread_info()->addr_limit.seg)) ? 0 : 1) + +#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) +#define __access_ok(addr,size) (__range_ok(addr,size) == 0) + +/* + * Uh, these should become the main single-value transfer routines ... + * They automatically use the right size if we just have the right + * pointer type ... + * + * As MIPS uses the same address space for kernel and user data, we + * can just do these as direct assignments. + * + * Careful to not + * (a) re-use the arguments for side effects (sizeof is ok) + * (b) require any knowledge of processes at this stage + */ +#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) +#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) + +/* + * The "__xxx" versions do not do address space checking, useful when + * doing multiple accesses to the same area (the user has to do the + * checks by hand with "access_ok()") + */ +#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) +#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) + +/* + * The "xxx_ret" versions return constant specified in third argument, if + * something bad happens. These macros can be optimized for the + * case of just returning from the function xxx_ret is used. + */ + +#define put_user_ret(x,ptr,ret) ({ \ +if (put_user(x,ptr)) return ret; }) + +#define get_user_ret(x,ptr,ret) ({ \ +if (get_user(x,ptr)) return ret; }) + +#define __put_user_ret(x,ptr,ret) ({ \ +if (__put_user(x,ptr)) return ret; }) + +#define __get_user_ret(x,ptr,ret) ({ \ +if (__get_user(x,ptr)) return ret; }) + +struct __large_struct { unsigned long buf[100]; }; +#define __m(x) (*(struct __large_struct *)(x)) + +#define __get_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: \ + retval = __get_user_asm_b(x, ptr); \ + break; \ + case 2: \ + retval = __get_user_asm_w(x, ptr); \ + break; \ + case 4: \ + retval = __get_user_asm_l(x, ptr); \ + break; \ + case 8: \ + retval = __get_user_asm_q(x, ptr); \ + break; \ + default: \ + __get_user_unknown(); \ + break; \ + } \ +} while (0) + +#define __get_user_nocheck(x,ptr,size) \ +({ \ + long __gu_err, __gu_val; \ + __get_user_size((void *)&__gu_val, (long)(ptr), \ + (size), __gu_err); \ + (x) = (__typeof__(*(ptr)))__gu_val; \ + __gu_err; \ +}) + +#define __get_user_check(x,ptr,size) \ +({ \ + long __gu_addr = (long)(ptr); \ + long __gu_err = -EFAULT, __gu_val; \ + if (__access_ok(__gu_addr, (size))) \ + __get_user_size((void *)&__gu_val, __gu_addr, \ + (size), __gu_err); \ + (x) = (__typeof__(*(ptr))) __gu_val; \ + __gu_err; \ +}) + +extern long __get_user_asm_b(void *, long); +extern long __get_user_asm_w(void *, long); +extern long __get_user_asm_l(void *, long); +extern long __get_user_asm_q(void *, long); +extern void __get_user_unknown(void); + +#define __put_user_size(x,ptr,size,retval) \ +do { \ + retval = 0; \ + switch (size) { \ + case 1: \ + retval = __put_user_asm_b(x, ptr); \ + break; \ + case 2: \ + retval = __put_user_asm_w(x, ptr); \ + break; \ + case 4: \ + retval = __put_user_asm_l(x, ptr); \ + break; \ + case 8: \ + retval = __put_user_asm_q(x, ptr); \ + break; \ + default: \ + __put_user_unknown(); \ + } \ +} while (0) + +#define __put_user_nocheck(x,ptr,size) \ +({ \ + long __pu_err; \ + __typeof__(*(ptr)) __pu_val = (x); \ + __put_user_size((void *)&__pu_val, (long)(ptr), (size), __pu_err); \ + __pu_err; \ +}) + +#define __put_user_check(x,ptr,size) \ +({ \ + long __pu_err = -EFAULT; \ + long __pu_addr = (long)(ptr); \ + __typeof__(*(ptr)) __pu_val = (x); \ + \ + if (__access_ok(__pu_addr, (size))) \ + __put_user_size((void *)&__pu_val, __pu_addr, (size), __pu_err);\ + __pu_err; \ +}) + +extern long __put_user_asm_b(void *, long); +extern long __put_user_asm_w(void *, long); +extern long __put_user_asm_l(void *, long); +extern long __put_user_asm_q(void *, long); +extern void __put_user_unknown(void); + + +/* Generic arbitrary sized copy. */ +/* Return the number of bytes NOT copied */ +/* XXX: should be such that: 4byte and the rest. */ +extern __kernel_size_t __copy_user(void *__to, const void *__from, __kernel_size_t __n); + +#define copy_to_user(to,from,n) ({ \ +void *__copy_to = (void *) (to); \ +__kernel_size_t __copy_size = (__kernel_size_t) (n); \ +__kernel_size_t __copy_res; \ +if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ +__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +#define copy_to_user_ret(to,from,n,retval) ({ \ +if (copy_to_user(to,from,n)) \ + return retval; \ +}) + +#define __copy_to_user(to,from,n) \ + __copy_user((void *)(to), \ + (void *)(from), n) + +#define __copy_to_user_ret(to,from,n,retval) ({ \ +if (__copy_to_user(to,from,n)) \ + return retval; \ +}) + +#define copy_from_user(to,from,n) ({ \ +void *__copy_to = (void *) (to); \ +void *__copy_from = (void *) (from); \ +__kernel_size_t __copy_size = (__kernel_size_t) (n); \ +__kernel_size_t __copy_res; \ +if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ +__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ +} else __copy_res = __copy_size; \ +__copy_res; }) + +#define copy_from_user_ret(to,from,n,retval) ({ \ +if (copy_from_user(to,from,n)) \ + return retval; \ +}) + +#define __copy_from_user(to,from,n) \ + __copy_user((void *)(to), \ + (void *)(from), n) + +#define __copy_from_user_ret(to,from,n,retval) ({ \ +if (__copy_from_user(to,from,n)) \ + return retval; \ +}) + +#define __copy_to_user_inatomic __copy_to_user +#define __copy_from_user_inatomic __copy_from_user + +/* XXX: Not sure it works well.. + should be such that: 4byte clear and the rest. */ +extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size); + +#define clear_user(addr,n) ({ \ +void * __cl_addr = (addr); \ +unsigned long __cl_size = (n); \ +if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \ +__cl_size = __clear_user(__cl_addr, __cl_size); \ +__cl_size; }) + +extern int __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count); + +#define strncpy_from_user(dest,src,count) ({ \ +unsigned long __sfu_src = (unsigned long) (src); \ +int __sfu_count = (int) (count); \ +long __sfu_res = -EFAULT; \ +if(__access_ok(__sfu_src, __sfu_count)) { \ +__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ +} __sfu_res; }) + +#define strlen_user(str) strnlen_user(str, ~0UL >> 1) + +/* + * Return the size of a string (including the ending 0!) + */ +extern long __strnlen_user(const char *__s, long __n); + +static inline long strnlen_user(const char *s, long n) +{ + if (!__addr_ok(s)) + return 0; + else + return __strnlen_user(s, n); +} + +struct exception_table_entry +{ + unsigned long insn, fixup; +}; + +#define ARCH_HAS_SEARCH_EXTABLE + +/* Returns 0 if exception not found and fixup.unit otherwise. */ +extern unsigned long search_exception_table(unsigned long addr); +extern const struct exception_table_entry *search_exception_tables (unsigned long addr); + +#endif /* __ASM_SH_UACCESS_64_H */ diff -puN include/asm-sh/unistd.h~git-sh include/asm-sh/unistd.h --- a/include/asm-sh/unistd.h~git-sh +++ a/include/asm-sh/unistd.h @@ -1,376 +1,5 @@ -#ifndef __ASM_SH_UNISTD_H -#define __ASM_SH_UNISTD_H - -/* - * Copyright (C) 1999 Niibe Yutaka - */ - -/* - * 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 -#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 -#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 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#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 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86old 113 -#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 -#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 -#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_streams1 188 /* some people actually want it */ -#define __NR_streams2 189 /* some people actually want it */ -#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 -/* 223 is unused */ -#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_add_key 285 -#define __NR_request_key 286 -#define __NR_keyctl 287 -#define __NR_ioprio_set 288 -#define __NR_ioprio_get 289 -#define __NR_inotify_init 290 -#define __NR_inotify_add_watch 291 -#define __NR_inotify_rm_watch 292 -/* 293 is unused */ -#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 322 -#define __NR_eventfd 323 -#define __NR_fallocate 324 - -#define NR_syscalls 325 - -#ifdef __KERNEL__ - -#define __ARCH_WANT_IPC_PARSE_VERSION -#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_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#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_RT_SIGACTION -#define __ARCH_WANT_SYS_RT_SIGSUSPEND - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#ifndef cond_syscall -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") +#ifdef CONFIG_SUPERH32 +# include "unistd_32.h" +#else +# include "unistd_64.h" #endif - -#endif /* __KERNEL__ */ -#endif /* __ASM_SH_UNISTD_H */ diff -puN /dev/null include/asm-sh/unistd_32.h --- /dev/null +++ a/include/asm-sh/unistd_32.h @@ -0,0 +1,376 @@ +#ifndef __ASM_SH_UNISTD_H +#define __ASM_SH_UNISTD_H + +/* + * Copyright (C) 1999 Niibe Yutaka + */ + +/* + * 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 +#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 +#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 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#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 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86old 113 +#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 +#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 +#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_streams1 188 /* some people actually want it */ +#define __NR_streams2 189 /* some people actually want it */ +#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 +/* 223 is unused */ +#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_add_key 285 +#define __NR_request_key 286 +#define __NR_keyctl 287 +#define __NR_ioprio_set 288 +#define __NR_ioprio_get 289 +#define __NR_inotify_init 290 +#define __NR_inotify_add_watch 291 +#define __NR_inotify_rm_watch 292 +/* 293 is unused */ +#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 322 +#define __NR_eventfd 323 +#define __NR_fallocate 324 + +#define NR_syscalls 325 + +#ifdef __KERNEL__ + +#define __ARCH_WANT_IPC_PARSE_VERSION +#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_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#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_RT_SIGACTION +#define __ARCH_WANT_SYS_RT_SIGSUSPEND + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#ifndef cond_syscall +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") +#endif + +#endif /* __KERNEL__ */ +#endif /* __ASM_SH_UNISTD_H */ diff -puN /dev/null include/asm-sh/unistd_64.h --- /dev/null +++ a/include/asm-sh/unistd_64.h @@ -0,0 +1,415 @@ +#ifndef __ASM_SH_UNISTD_64_H +#define __ASM_SH_UNISTD_64_H + +/* + * include/asm-sh/unistd_64.h + * + * This file contains the system call numbers. + * + * Copyright (C) 2000, 2001 Paolo Alberelli + * Copyright (C) 2003 - 2007 Paul Mundt + * Copyright (C) 2004 Sean McGoogan + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ +#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 +#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 +#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 +#define __NR_statfs 99 +#define __NR_fstatfs 100 +#define __NR_ioperm 101 +#define __NR_socketcall 102 /* old implementation of socket systemcall */ +#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 +#define __NR_iopl 110 +#define __NR_vhangup 111 +#define __NR_idle 112 +#define __NR_vm86old 113 +#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 +#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 +#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_streams1 188 /* some people actually want it */ +#define __NR_streams2 189 /* some people actually want it */ +#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 + +/* Non-multiplexed socket family */ +#define __NR_socket 220 +#define __NR_bind 221 +#define __NR_connect 222 +#define __NR_listen 223 +#define __NR_accept 224 +#define __NR_getsockname 225 +#define __NR_getpeername 226 +#define __NR_socketpair 227 +#define __NR_send 228 +#define __NR_sendto 229 +#define __NR_recv 230 +#define __NR_recvfrom 231 +#define __NR_shutdown 232 +#define __NR_setsockopt 233 +#define __NR_getsockopt 234 +#define __NR_sendmsg 235 +#define __NR_recvmsg 236 + +/* Non-multiplexed IPC family */ +#define __NR_semop 237 +#define __NR_semget 238 +#define __NR_semctl 239 +#define __NR_msgsnd 240 +#define __NR_msgrcv 241 +#define __NR_msgget 242 +#define __NR_msgctl 243 +#if 0 +#define __NR_shmatcall 244 +#endif +#define __NR_shmdt 245 +#define __NR_shmget 246 +#define __NR_shmctl 247 + +#define __NR_getdents64 248 +#define __NR_fcntl64 249 +/* 223 is unused */ +#define __NR_gettid 252 +#define __NR_readahead 253 +#define __NR_setxattr 254 +#define __NR_lsetxattr 255 +#define __NR_fsetxattr 256 +#define __NR_getxattr 257 +#define __NR_lgetxattr 258 +#define __NR_fgetxattr 269 +#define __NR_listxattr 260 +#define __NR_llistxattr 261 +#define __NR_flistxattr 262 +#define __NR_removexattr 263 +#define __NR_lremovexattr 264 +#define __NR_fremovexattr 265 +#define __NR_tkill 266 +#define __NR_sendfile64 267 +#define __NR_futex 268 +#define __NR_sched_setaffinity 269 +#define __NR_sched_getaffinity 270 +#define __NR_set_thread_area 271 +#define __NR_get_thread_area 272 +#define __NR_io_setup 273 +#define __NR_io_destroy 274 +#define __NR_io_getevents 275 +#define __NR_io_submit 276 +#define __NR_io_cancel 277 +#define __NR_fadvise64 278 +#define __NR_exit_group 280 + +#define __NR_lookup_dcookie 281 +#define __NR_epoll_create 282 +#define __NR_epoll_ctl 283 +#define __NR_epoll_wait 284 +#define __NR_remap_file_pages 285 +#define __NR_set_tid_address 286 +#define __NR_timer_create 287 +#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 296 +#define __NR_fstatfs64 297 +#define __NR_tgkill 298 +#define __NR_utimes 299 +#define __NR_fadvise64_64 300 +#define __NR_vserver 301 +#define __NR_mbind 302 +#define __NR_get_mempolicy 303 +#define __NR_set_mempolicy 304 +#define __NR_mq_open 305 +#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 311 +#define __NR_waitid 312 +#define __NR_add_key 313 +#define __NR_request_key 314 +#define __NR_keyctl 315 +#define __NR_ioprio_set 316 +#define __NR_ioprio_get 317 +#define __NR_inotify_init 318 +#define __NR_inotify_add_watch 319 +#define __NR_inotify_rm_watch 320 +/* 321 is unused */ +#define __NR_migrate_pages 322 +#define __NR_openat 323 +#define __NR_mkdirat 324 +#define __NR_mknodat 325 +#define __NR_fchownat 326 +#define __NR_futimesat 327 +#define __NR_fstatat64 328 +#define __NR_unlinkat 329 +#define __NR_renameat 330 +#define __NR_linkat 331 +#define __NR_symlinkat 332 +#define __NR_readlinkat 333 +#define __NR_fchmodat 334 +#define __NR_faccessat 335 +#define __NR_pselect6 336 +#define __NR_ppoll 337 +#define __NR_unshare 338 +#define __NR_set_robust_list 339 +#define __NR_get_robust_list 340 +#define __NR_splice 341 +#define __NR_sync_file_range 342 +#define __NR_tee 343 +#define __NR_vmsplice 344 +#define __NR_move_pages 345 +#define __NR_getcpu 346 +#define __NR_epoll_pwait 347 +#define __NR_utimensat 348 +#define __NR_signalfd 349 +#define __NR_timerfd 350 +#define __NR_eventfd 351 +#define __NR_fallocate 352 + +#ifdef __KERNEL__ + +#define NR_syscalls 353 + +#define __ARCH_WANT_IPC_PARSE_VERSION +#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_PAUSE +#define __ARCH_WANT_SYS_SGETMASK +#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_RT_SIGACTION + +/* + * "Conditional" syscalls + * + * What we want is __attribute__((weak,alias("sys_ni_syscall"))), + * but it doesn't work on all toolchains, so we just do it by hand + */ +#ifndef cond_syscall +#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") +#endif + +#endif /* __KERNEL__ */ +#endif /* __ASM_SH_UNISTD_64_H */ diff -puN include/asm-sh/user.h~git-sh include/asm-sh/user.h --- a/include/asm-sh/user.h~git-sh +++ a/include/asm-sh/user.h @@ -27,12 +27,19 @@ * to write an integer number of pages. */ +#if defined(__SH5__) || defined(CONFIG_CPU_SH5) +struct user_fpu_struct { + unsigned long fp_regs[32]; + unsigned int fpscr; +}; +#else struct user_fpu_struct { unsigned long fp_regs[16]; unsigned long xfp_regs[16]; unsigned long fpscr; unsigned long fpul; }; +#endif struct user { struct pt_regs regs; /* entire machine state */ diff -puN include/asm-sh/voyagergx.h~git-sh include/asm-sh/voyagergx.h --- a/include/asm-sh/voyagergx.h~git-sh +++ a/include/asm-sh/voyagergx.h @@ -213,7 +213,7 @@ /* ----- Power mode 1 clock register -------------------------- */ #define POWER_MODE1_CLOCK (0x00004C + VOYAGER_BASE) -/* ----- Power mode controll register ------------------------- */ +/* ----- Power mode control register ------------------------- */ #define POWER_MODE_CTRL (0x000054 + VOYAGER_BASE) /* ----- Miscellaneous Timing register ------------------------ */ diff -puN include/asm-sh64/Kbuild~git-sh /dev/null --- a/include/asm-sh64/Kbuild +++ /dev/null @@ -1 +0,0 @@ -include include/asm-generic/Kbuild.asm diff -puN include/asm-sh64/a.out.h~git-sh /dev/null --- a/include/asm-sh64/a.out.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __ASM_SH64_A_OUT_H -#define __ASM_SH64_A_OUT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/a.out.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP - -#endif - -#endif /* __ASM_SH64_A_OUT_H */ diff -puN include/asm-sh64/atomic.h~git-sh /dev/null --- a/include/asm-sh64/atomic.h +++ /dev/null @@ -1,158 +0,0 @@ -#ifndef __ASM_SH64_ATOMIC_H -#define __ASM_SH64_ATOMIC_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/atomic.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -/* - * Atomic operations that C can't guarantee us. Useful for - * resource counting etc.. - * - */ - -typedef struct { volatile int counter; } atomic_t; - -#define ATOMIC_INIT(i) ( (atomic_t) { (i) } ) - -#define atomic_read(v) ((v)->counter) -#define atomic_set(v,i) ((v)->counter = (i)) - -#include - -/* - * To get proper branch prediction for the main line, we must branch - * forward to code at the end of this object's .text section, then - * branch back to restart the operation. - */ - -static __inline__ void atomic_add(int i, atomic_t * v) -{ - unsigned long flags; - - local_irq_save(flags); - *(long *)v += i; - local_irq_restore(flags); -} - -static __inline__ void atomic_sub(int i, atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - *(long *)v -= i; - local_irq_restore(flags); -} - -static __inline__ int atomic_add_return(int i, atomic_t * v) -{ - unsigned long temp, flags; - - local_irq_save(flags); - temp = *(long *)v; - temp += i; - *(long *)v = temp; - local_irq_restore(flags); - - return temp; -} - -#define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) - -static __inline__ int atomic_sub_return(int i, atomic_t * v) -{ - unsigned long temp, flags; - - local_irq_save(flags); - temp = *(long *)v; - temp -= i; - *(long *)v = temp; - local_irq_restore(flags); - - return temp; -} - -#define atomic_dec_return(v) atomic_sub_return(1,(v)) -#define atomic_inc_return(v) atomic_add_return(1,(v)) - -/* - * atomic_inc_and_test - increment and test - * @v: pointer of type atomic_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -#define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) - -#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(v) atomic_add(1,(v)) -#define atomic_dec(v) atomic_sub(1,(v)) - -static inline int atomic_cmpxchg(atomic_t *v, int old, int new) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (likely(ret == old)) - v->counter = new; - local_irq_restore(flags); - - return ret; -} - -#define atomic_xchg(v, new) (xchg(&((v)->counter), new)) - -static inline int atomic_add_unless(atomic_t *v, int a, int u) -{ - int ret; - unsigned long flags; - - local_irq_save(flags); - ret = v->counter; - if (ret != u) - v->counter += a; - local_irq_restore(flags); - - return ret != u; -} -#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) - -static __inline__ void atomic_clear_mask(unsigned int mask, atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - *(long *)v &= ~mask; - local_irq_restore(flags); -} - -static __inline__ void atomic_set_mask(unsigned int mask, atomic_t *v) -{ - unsigned long flags; - - local_irq_save(flags); - *(long *)v |= mask; - local_irq_restore(flags); -} - -/* Atomic operations are already serializing on SH */ -#define smp_mb__before_atomic_dec() barrier() -#define smp_mb__after_atomic_dec() barrier() -#define smp_mb__before_atomic_inc() barrier() -#define smp_mb__after_atomic_inc() barrier() - -#include -#endif /* __ASM_SH64_ATOMIC_H */ diff -puN include/asm-sh64/auxvec.h~git-sh /dev/null --- a/include/asm-sh64/auxvec.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __ASM_SH64_AUXVEC_H -#define __ASM_SH64_AUXVEC_H - -#endif /* __ASM_SH64_AUXVEC_H */ diff -puN include/asm-sh64/bitops.h~git-sh /dev/null --- a/include/asm-sh64/bitops.h +++ /dev/null @@ -1,155 +0,0 @@ -#ifndef __ASM_SH64_BITOPS_H -#define __ASM_SH64_BITOPS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/bitops.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - */ - -#ifdef __KERNEL__ - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -#include -#include -/* For __swab32 */ -#include - -static __inline__ void set_bit(int nr, volatile void * addr) -{ - int mask; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a |= mask; - local_irq_restore(flags); -} - -/* - * clear_bit() doesn't provide any barrier for the compiler. - */ -#define smp_mb__before_clear_bit() barrier() -#define smp_mb__after_clear_bit() barrier() -static inline void clear_bit(int nr, volatile unsigned long *a) -{ - int mask; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a &= ~mask; - local_irq_restore(flags); -} - -static __inline__ void change_bit(int nr, volatile void * addr) -{ - int mask; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - *a ^= mask; - local_irq_restore(flags); -} - -static __inline__ int test_and_set_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a |= mask; - local_irq_restore(flags); - - return retval; -} - -static __inline__ int test_and_clear_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a &= ~mask; - local_irq_restore(flags); - - return retval; -} - -static __inline__ int test_and_change_bit(int nr, volatile void * addr) -{ - int mask, retval; - volatile unsigned int *a = addr; - unsigned long flags; - - a += nr >> 5; - mask = 1 << (nr & 0x1f); - local_irq_save(flags); - retval = (mask & *a) != 0; - *a ^= mask; - local_irq_restore(flags); - - return retval; -} - -#include - -static __inline__ unsigned long ffz(unsigned long word) -{ - unsigned long result, __d2, __d3; - - __asm__("gettr tr0, %2\n\t" - "pta $+32, tr0\n\t" - "andi %1, 1, %3\n\t" - "beq %3, r63, tr0\n\t" - "pta $+4, tr0\n" - "0:\n\t" - "shlri.l %1, 1, %1\n\t" - "addi %0, 1, %0\n\t" - "andi %1, 1, %3\n\t" - "beqi %3, 1, tr0\n" - "1:\n\t" - "ptabs %2, tr0\n\t" - : "=r" (result), "=r" (word), "=r" (__d2), "=r" (__d3) - : "0" (0L), "1" (word)); - - return result; -} - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_BITOPS_H */ diff -puN include/asm-sh64/bug.h~git-sh /dev/null --- a/include/asm-sh64/bug.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __ASM_SH64_BUG_H -#define __ASM_SH64_BUG_H - -#ifdef CONFIG_BUG -/* - * Tell the user there is some problem, then force a segfault (in process - * context) or a panic (interrupt context). - */ -#define BUG() do { \ - printk("kernel BUG at %s:%d!\n", __FILE__, __LINE__); \ - *(volatile int *)0 = 0; \ -} while (0) - -#define HAVE_ARCH_BUG -#endif - -#include - -#endif /* __ASM_SH64_BUG_H */ diff -puN include/asm-sh64/bugs.h~git-sh /dev/null --- a/include/asm-sh64/bugs.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __ASM_SH64_BUGS_H -#define __ASM_SH64_BUGS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/bugs.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -/* - * This is included by init/main.c to check for architecture-dependent bugs. - * - * Needs: - * void check_bugs(void); - */ - -/* - * I don't know of any Super-H bugs yet. - */ - -#include - -static void __init check_bugs(void) -{ - extern char *get_cpu_subtype(void); - extern unsigned long loops_per_jiffy; - - cpu_data->loops_per_jiffy = loops_per_jiffy; - - printk("CPU: %s\n", get_cpu_subtype()); -} -#endif /* __ASM_SH64_BUGS_H */ diff -puN include/asm-sh64/byteorder.h~git-sh /dev/null --- a/include/asm-sh64/byteorder.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __ASM_SH64_BYTEORDER_H -#define __ASM_SH64_BYTEORDER_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/byteorder.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include - -static inline __attribute_const__ __u32 ___arch__swab32(__u32 x) -{ - __asm__("byterev %0, %0\n\t" - "shari %0, 32, %0" - : "=r" (x) - : "0" (x)); - return x; -} - -static inline __attribute_const__ __u16 ___arch__swab16(__u16 x) -{ - __asm__("byterev %0, %0\n\t" - "shari %0, 48, %0" - : "=r" (x) - : "0" (x)); - return x; -} - -#define __arch__swab32(x) ___arch__swab32(x) -#define __arch__swab16(x) ___arch__swab16(x) - -#if !defined(__STRICT_ANSI__) || defined(__KERNEL__) -# define __BYTEORDER_HAS_U64__ -# define __SWAB_64_THRU_32__ -#endif - -#ifdef __LITTLE_ENDIAN__ -#include -#else -#include -#endif - -#endif /* __ASM_SH64_BYTEORDER_H */ diff -puN include/asm-sh64/cache.h~git-sh /dev/null --- a/include/asm-sh64/cache.h +++ /dev/null @@ -1,139 +0,0 @@ -#ifndef __ASM_SH64_CACHE_H -#define __ASM_SH64_CACHE_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/cache.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - */ -#include - -#define L1_CACHE_SHIFT 5 -/* bytes per L1 cache line */ -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) -#define L1_CACHE_ALIGN_MASK (~(L1_CACHE_BYTES - 1)) -#define L1_CACHE_ALIGN(x) (((x)+(L1_CACHE_BYTES - 1)) & L1_CACHE_ALIGN_MASK) -#define L1_CACHE_SIZE_BYTES (L1_CACHE_BYTES << 10) - -#ifdef MODULE -#define __cacheline_aligned __attribute__((__aligned__(L1_CACHE_BYTES))) -#else -#define __cacheline_aligned \ - __attribute__((__aligned__(L1_CACHE_BYTES), \ - __section__(".data.cacheline_aligned"))) -#endif - -/* - * Control Registers. - */ -#define ICCR_BASE 0x01600000 /* Instruction Cache Control Register */ -#define ICCR_REG0 0 /* Register 0 offset */ -#define ICCR_REG1 1 /* Register 1 offset */ -#define ICCR0 ICCR_BASE+ICCR_REG0 -#define ICCR1 ICCR_BASE+ICCR_REG1 - -#define ICCR0_OFF 0x0 /* Set ICACHE off */ -#define ICCR0_ON 0x1 /* Set ICACHE on */ -#define ICCR0_ICI 0x2 /* Invalidate all in IC */ - -#define ICCR1_NOLOCK 0x0 /* Set No Locking */ - -#define OCCR_BASE 0x01E00000 /* Operand Cache Control Register */ -#define OCCR_REG0 0 /* Register 0 offset */ -#define OCCR_REG1 1 /* Register 1 offset */ -#define OCCR0 OCCR_BASE+OCCR_REG0 -#define OCCR1 OCCR_BASE+OCCR_REG1 - -#define OCCR0_OFF 0x0 /* Set OCACHE off */ -#define OCCR0_ON 0x1 /* Set OCACHE on */ -#define OCCR0_OCI 0x2 /* Invalidate all in OC */ -#define OCCR0_WT 0x4 /* Set OCACHE in WT Mode */ -#define OCCR0_WB 0x0 /* Set OCACHE in WB Mode */ - -#define OCCR1_NOLOCK 0x0 /* Set No Locking */ - - -/* - * SH-5 - * A bit of description here, for neff=32. - * - * |<--- tag (19 bits) --->| - * +-----------------------------+-----------------+------+----------+------+ - * | | | ways |set index |offset| - * +-----------------------------+-----------------+------+----------+------+ - * ^ 2 bits 8 bits 5 bits - * +- Bit 31 - * - * Cacheline size is based on offset: 5 bits = 32 bytes per line - * A cache line is identified by a tag + set but OCACHETAG/ICACHETAG - * have a broader space for registers. These are outlined by - * CACHE_?C_*_STEP below. - * - */ - -/* Valid and Dirty bits */ -#define SH_CACHE_VALID (1LL<<0) -#define SH_CACHE_UPDATED (1LL<<57) - -/* Cache flags */ -#define SH_CACHE_MODE_WT (1LL<<0) -#define SH_CACHE_MODE_WB (1LL<<1) - -#ifndef __ASSEMBLY__ - -/* - * Cache information structure. - * - * Defined for both I and D cache, per-processor. - */ -struct cache_info { - unsigned int ways; - unsigned int sets; - unsigned int linesz; - - unsigned int way_shift; - unsigned int entry_shift; - unsigned int set_shift; - unsigned int way_step_shift; - unsigned int asid_shift; - - unsigned int way_ofs; - - unsigned int asid_mask; - unsigned int idx_mask; - unsigned int epn_mask; - - unsigned long flags; -}; - -#endif /* __ASSEMBLY__ */ - -/* Instruction cache */ -#define CACHE_IC_ADDRESS_ARRAY 0x01000000 - -/* Operand Cache */ -#define CACHE_OC_ADDRESS_ARRAY 0x01800000 - -/* These declarations relate to cache 'synonyms' in the operand cache. A - 'synonym' occurs where effective address bits overlap between those used for - indexing the cache sets and those passed to the MMU for translation. In the - case of SH5-101 & SH5-103, only bit 12 is affected for 4k pages. */ - -#define CACHE_OC_N_SYNBITS 1 /* Number of synonym bits */ -#define CACHE_OC_SYN_SHIFT 12 -/* Mask to select synonym bit(s) */ -#define CACHE_OC_SYN_MASK (((1UL< - -struct vm_area_struct; -struct page; -struct mm_struct; - -extern void flush_cache_all(void); -extern void flush_cache_mm(struct mm_struct *mm); -extern void flush_cache_sigtramp(unsigned long start, unsigned long end); -extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_cache_page(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn); -extern void flush_dcache_page(struct page *pg); -extern void flush_icache_range(unsigned long start, unsigned long end); -extern void flush_icache_user_range(struct vm_area_struct *vma, - struct page *page, unsigned long addr, - int len); - -#define flush_cache_dup_mm(mm) flush_cache_mm(mm) - -#define flush_dcache_mmap_lock(mapping) do { } while (0) -#define flush_dcache_mmap_unlock(mapping) do { } while (0) - -#define flush_cache_vmap(start, end) flush_cache_all() -#define flush_cache_vunmap(start, end) flush_cache_all() - -#define flush_icache_page(vma, page) do { } while (0) - -#define copy_to_user_page(vma, page, vaddr, dst, src, len) \ - do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ - 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) \ - do { \ - flush_cache_page(vma, vaddr, page_to_pfn(page));\ - memcpy(dst, src, len); \ - } while (0) - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_SH64_CACHEFLUSH_H */ - diff -puN include/asm-sh64/cayman.h~git-sh /dev/null --- a/include/asm-sh64/cayman.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/cayman.h - * - * Cayman definitions - * - * Global defintions for the SH5 Cayman board - * - * Copyright (C) 2002 Stuart Menefy - */ - - -/* Setup for the SMSC FDC37C935 / LAN91C100FD */ -#define SMSC_IRQ IRQ_IRL1 - -/* Setup for PCI Bus 2, which transmits interrupts via the EPLD */ -#define PCI2_IRQ IRQ_IRL3 diff -puN include/asm-sh64/checksum.h~git-sh /dev/null --- a/include/asm-sh64/checksum.h +++ /dev/null @@ -1,82 +0,0 @@ -#ifndef __ASM_SH64_CHECKSUM_H -#define __ASM_SH64_CHECKSUM_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/checksum.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include - -/* - * 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 - */ -asmlinkage __wsum csum_partial(const void *buff, int len, __wsum sum); - -/* - * Note: when you get a NULL pointer exception here this means someone - * passed in an incorrect kernel address to one of these functions. - * - * If you use these functions directly please don't forget the - * access_ok(). - */ - - -__wsum csum_partial_copy_nocheck(const void *src, void *dst, int len, - __wsum sum); - -__wsum csum_partial_copy_from_user(const void __user *src, void *dst, - int len, __wsum sum, int *err_ptr); - -static inline __sum16 csum_fold(__wsum csum) -{ - u32 sum = (__force u32)csum; - sum = (sum & 0xffff) + (sum >> 16); - sum = (sum & 0xffff) + (sum >> 16); - return (__force __sum16)~sum; -} - -__sum16 ip_fast_csum(const void *iph, unsigned int ihl); - -__wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, - unsigned short len, unsigned short proto, - __wsum sum); - -/* - * computes the checksum of the TCP/UDP pseudo-header - * returns a 16-bit checksum, already complemented - */ -static inline __sum16 csum_tcpudp_magic(__be32 saddr, __be32 daddr, - unsigned short len, - unsigned short proto, - __wsum sum) -{ - return csum_fold(csum_tcpudp_nofold(saddr,daddr,len,proto,sum)); -} - -/* - * this routine is used for miscellaneous IP-like checksums, mainly - * in icmp.c - */ -static inline __sum16 ip_compute_csum(const void *buff, int len) -{ - return csum_fold(csum_partial(buff, len, 0)); -} - -#endif /* __ASM_SH64_CHECKSUM_H */ - diff -puN include/asm-sh64/cpumask.h~git-sh /dev/null --- a/include/asm-sh64/cpumask.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_CPUMASK_H -#define __ASM_SH64_CPUMASK_H - -#include - -#endif /* __ASM_SH64_CPUMASK_H */ diff -puN include/asm-sh64/cputime.h~git-sh /dev/null --- a/include/asm-sh64/cputime.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __SH64_CPUTIME_H -#define __SH64_CPUTIME_H - -#include - -#endif /* __SH64_CPUTIME_H */ diff -puN include/asm-sh64/current.h~git-sh /dev/null --- a/include/asm-sh64/current.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __ASM_SH64_CURRENT_H -#define __ASM_SH64_CURRENT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/current.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -#include - -struct task_struct; - -static __inline__ struct task_struct * get_current(void) -{ - return current_thread_info()->task; -} - -#define current get_current() - -#endif /* __ASM_SH64_CURRENT_H */ - diff -puN include/asm-sh64/delay.h~git-sh /dev/null --- a/include/asm-sh64/delay.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef __ASM_SH64_DELAY_H -#define __ASM_SH64_DELAY_H - -extern void __delay(int loops); -extern void __udelay(unsigned long long usecs, unsigned long lpj); -extern void __ndelay(unsigned long long nsecs, unsigned long lpj); -extern void udelay(unsigned long usecs); -extern void ndelay(unsigned long nsecs); - -#endif /* __ASM_SH64_DELAY_H */ - diff -puN include/asm-sh64/device.h~git-sh /dev/null --- a/include/asm-sh64/device.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Arch specific extensions to struct device - * - * This file is released under the GPLv2 - */ -#include - diff -puN include/asm-sh64/div64.h~git-sh /dev/null --- a/include/asm-sh64/div64.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_DIV64_H -#define __ASM_SH64_DIV64_H - -#include - -#endif /* __ASM_SH64_DIV64_H */ diff -puN include/asm-sh64/dma-mapping.h~git-sh /dev/null --- a/include/asm-sh64/dma-mapping.h +++ /dev/null @@ -1,194 +0,0 @@ -#ifndef __ASM_SH_DMA_MAPPING_H -#define __ASM_SH_DMA_MAPPING_H - -#include -#include -#include - -struct pci_dev; -extern void *consistent_alloc(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle); -extern void consistent_free(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle); - -#define dma_supported(dev, mask) (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_alloc_coherent(struct device *dev, size_t size, - dma_addr_t *dma_handle, gfp_t flag) -{ - return consistent_alloc(NULL, size, dma_handle); -} - -static inline void dma_free_coherent(struct device *dev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - consistent_free(NULL, size, vaddr, dma_handle); -} - -#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f) -#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h) -#define dma_is_consistent(d, h) (1) - -static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size, - enum dma_data_direction dir) -{ - unsigned long start = (unsigned long) vaddr; - unsigned long s = start & L1_CACHE_ALIGN_MASK; - unsigned long e = (start + size) & L1_CACHE_ALIGN_MASK; - - for (; s <= e; s += L1_CACHE_BYTES) - asm volatile ("ocbp %0, 0" : : "r" (s)); -} - -static inline dma_addr_t dma_map_single(struct device *dev, - void *ptr, size_t size, - enum dma_data_direction dir) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return virt_to_phys(ptr); -#endif - dma_cache_sync(dev, ptr, size, dir); - - return virt_to_phys(ptr); -} - -#define dma_unmap_single(dev, addr, size, dir) do { } while (0) - -static inline int dma_map_sg(struct device *dev, struct scatterlist *sg, - int nents, enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nents; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); -#endif - sg[i].dma_address = sg_phys(&sg[i]); - } - - return nents; -} - -#define dma_unmap_sg(dev, sg, nents, dir) do { } while (0) - -static inline dma_addr_t dma_map_page(struct device *dev, struct page *page, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ - return dma_map_single(dev, page_address(page) + offset, size, dir); -} - -static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address, - size_t size, enum dma_data_direction dir) -{ - dma_unmap_single(dev, dma_address, size, dir); -} - -static inline void dma_sync_single(struct device *dev, dma_addr_t dma_handle, - size_t size, enum dma_data_direction dir) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle), size, dir); -} - -static inline void dma_sync_single_range(struct device *dev, - dma_addr_t dma_handle, - unsigned long offset, size_t size, - enum dma_data_direction dir) -{ -#if defined(CONFIG_PCI) && !defined(CONFIG_SH_PCIDMA_NONCOHERENT) - if (dev->bus == &pci_bus_type) - return; -#endif - dma_cache_sync(dev, phys_to_virt(dma_handle) + offset, size, dir); -} - -static inline void dma_sync_sg(struct device *dev, struct scatterlist *sg, - int nelems, enum dma_data_direction dir) -{ - int i; - - for (i = 0; i < nelems; i++) { -#if !defined(CONFIG_PCI) || defined(CONFIG_SH_PCIDMA_NONCOHERENT) - dma_cache_sync(dev, sg_virt(&sg[i]), sg[i].length, dir); -#endif - sg[i].dma_address = sg_phys(&sg[i]); - } -} - -static inline void dma_sync_single_for_cpu(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); -} - -static inline void dma_sync_single_for_device(struct device *dev, - dma_addr_t dma_handle, size_t size, - enum dma_data_direction dir) -{ - dma_sync_single(dev, dma_handle, size, dir); -} - -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) -{ - dma_sync_single_for_cpu(dev, dma_handle+offset, size, 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) -{ - dma_sync_single_for_device(dev, dma_handle+offset, size, direction); -} - -static inline void dma_sync_sg_for_cpu(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); -} - -static inline void dma_sync_sg_for_device(struct device *dev, - struct scatterlist *sg, int nelems, - enum dma_data_direction dir) -{ - dma_sync_sg(dev, sg, nelems, dir); -} - -static inline int dma_get_cache_alignment(void) -{ - /* - * Each processor family will define its own L1_CACHE_SHIFT, - * L1_CACHE_BYTES wraps to this, so this is always safe. - */ - return L1_CACHE_BYTES; -} - -static inline int dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} - -#endif /* __ASM_SH_DMA_MAPPING_H */ - diff -puN include/asm-sh64/dma.h~git-sh /dev/null --- a/include/asm-sh64/dma.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __ASM_SH64_DMA_H -#define __ASM_SH64_DMA_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/dma.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -#include -#include -#include - -#define MAX_DMA_CHANNELS 4 - -/* - * SH5 can DMA in any memory area. - * - * The static definition is dodgy because it should limit - * the highest DMA-able address based on the actual - * Physical memory available. This is actually performed - * at run time in defining the memory allowed to DMA_ZONE. - */ -#define MAX_DMA_ADDRESS ~(NPHYS_MASK) - -#define DMA_MODE_READ 0 -#define DMA_MODE_WRITE 1 - -#ifdef CONFIG_PCI -extern int isa_dma_bridge_buggy; -#else -#define isa_dma_bridge_buggy (0) -#endif - -#endif /* __ASM_SH64_DMA_H */ diff -puN include/asm-sh64/elf.h~git-sh /dev/null --- a/include/asm-sh64/elf.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef __ASM_SH64_ELF_H -#define __ASM_SH64_ELF_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/elf.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * ELF register definitions.. - */ - -#include -#include -#include - -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_fpu_struct elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ( (x)->e_machine == EM_SH ) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#ifdef __LITTLE_ENDIAN__ -#define ELF_DATA ELFDATA2LSB -#else -#define ELF_DATA ELFDATA2MSB -#endif -#define ELF_ARCH EM_SH - -#define USE_ELF_CORE_DUMP -#define ELF_EXEC_PAGESIZE 4096 - -/* 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 (2 * TASK_SIZE / 3) - -#define R_SH_DIR32 1 -#define R_SH_REL32 2 -#define R_SH_IMM_LOW16 246 -#define R_SH_IMM_LOW16_PCREL 247 -#define R_SH_IMM_MEDLOW16 248 -#define R_SH_IMM_MEDLOW16_PCREL 249 - -#define ELF_CORE_COPY_REGS(_dest,_regs) \ - memcpy((char *) &_dest, (char *) _regs, \ - sizeof(struct pt_regs)); - -/* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. This could be done in user space, - but it's not easy, and we've already done it here. */ - -#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. - - For the moment, we have only optimizations for the Intel generations, - but that could change... */ - -#define ELF_PLATFORM (NULL) - -#define ELF_PLAT_INIT(_r, load_addr) \ - do { _r->regs[0]=0; _r->regs[1]=0; _r->regs[2]=0; _r->regs[3]=0; \ - _r->regs[4]=0; _r->regs[5]=0; _r->regs[6]=0; _r->regs[7]=0; \ - _r->regs[8]=0; _r->regs[9]=0; _r->regs[10]=0; _r->regs[11]=0; \ - _r->regs[12]=0; _r->regs[13]=0; _r->regs[14]=0; _r->regs[15]=0; \ - _r->regs[16]=0; _r->regs[17]=0; _r->regs[18]=0; _r->regs[19]=0; \ - _r->regs[20]=0; _r->regs[21]=0; _r->regs[22]=0; _r->regs[23]=0; \ - _r->regs[24]=0; _r->regs[25]=0; _r->regs[26]=0; _r->regs[27]=0; \ - _r->regs[28]=0; _r->regs[29]=0; _r->regs[30]=0; _r->regs[31]=0; \ - _r->regs[32]=0; _r->regs[33]=0; _r->regs[34]=0; _r->regs[35]=0; \ - _r->regs[36]=0; _r->regs[37]=0; _r->regs[38]=0; _r->regs[39]=0; \ - _r->regs[40]=0; _r->regs[41]=0; _r->regs[42]=0; _r->regs[43]=0; \ - _r->regs[44]=0; _r->regs[45]=0; _r->regs[46]=0; _r->regs[47]=0; \ - _r->regs[48]=0; _r->regs[49]=0; _r->regs[50]=0; _r->regs[51]=0; \ - _r->regs[52]=0; _r->regs[53]=0; _r->regs[54]=0; _r->regs[55]=0; \ - _r->regs[56]=0; _r->regs[57]=0; _r->regs[58]=0; _r->regs[59]=0; \ - _r->regs[60]=0; _r->regs[61]=0; _r->regs[62]=0; \ - _r->tregs[0]=0; _r->tregs[1]=0; _r->tregs[2]=0; _r->tregs[3]=0; \ - _r->tregs[4]=0; _r->tregs[5]=0; _r->tregs[6]=0; _r->tregs[7]=0; \ - _r->sr = SR_FD | SR_MMU; } while (0) - -#ifdef __KERNEL__ -#define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) -#endif - -#endif /* __ASM_SH64_ELF_H */ diff -puN include/asm-sh64/emergency-restart.h~git-sh /dev/null --- a/include/asm-sh64/emergency-restart.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_EMERGENCY_RESTART_H -#define _ASM_EMERGENCY_RESTART_H - -#include - -#endif /* _ASM_EMERGENCY_RESTART_H */ diff -puN include/asm-sh64/errno.h~git-sh /dev/null --- a/include/asm-sh64/errno.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_ERRNO_H -#define __ASM_SH64_ERRNO_H - -#include - -#endif /* __ASM_SH64_ERRNO_H */ diff -puN include/asm-sh64/fb.h~git-sh /dev/null --- a/include/asm-sh64/fb.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _ASM_FB_H_ -#define _ASM_FB_H_ - -#include -#include -#include - -static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma, - unsigned long off) -{ - vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); -} - -static inline int fb_is_primary_device(struct fb_info *info) -{ - return 0; -} - -#endif /* _ASM_FB_H_ */ diff -puN include/asm-sh64/fcntl.h~git-sh /dev/null --- a/include/asm-sh64/fcntl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff -puN include/asm-sh64/futex.h~git-sh /dev/null --- a/include/asm-sh64/futex.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_FUTEX_H -#define _ASM_FUTEX_H - -#include - -#endif diff -puN include/asm-sh64/gpio.h~git-sh /dev/null --- a/include/asm-sh64/gpio.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH64_GPIO_H -#define __ASM_SH64_GPIO_H - -/* - * This is just a stub, so that every arch using sh-sci has a gpio.h - */ - -#endif /* __ASM_SH64_GPIO_H */ diff -puN include/asm-sh64/hardirq.h~git-sh /dev/null --- a/include/asm-sh64/hardirq.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __ASM_SH64_HARDIRQ_H -#define __ASM_SH64_HARDIRQ_H - -#include -#include - -/* entry.S is sensitive to the offsets of these fields */ -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -/* arch/sh64/kernel/irq.c */ -extern void ack_bad_irq(unsigned int irq); - -#endif /* __ASM_SH64_HARDIRQ_H */ - diff -puN include/asm-sh64/hardware.h~git-sh /dev/null --- a/include/asm-sh64/hardware.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ASM_SH64_HARDWARE_H -#define __ASM_SH64_HARDWARE_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/hardware.h - * - * Copyright (C) 2002 Stuart Menefy - * Copyright (C) 2003 Paul Mundt - * - * Defitions of the locations of registers in the physical address space. - */ - -#define PHYS_PERIPHERAL_BLOCK 0x09000000 -#define PHYS_DMAC_BLOCK 0x0e000000 -#define PHYS_PCI_BLOCK 0x60000000 -#define PHYS_EMI_BLOCK 0xff000000 - -#endif /* __ASM_SH64_HARDWARE_H */ diff -puN include/asm-sh64/hw_irq.h~git-sh /dev/null --- a/include/asm-sh64/hw_irq.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ASM_SH64_HW_IRQ_H -#define __ASM_SH64_HW_IRQ_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/hw_irq.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#endif /* __ASM_SH64_HW_IRQ_H */ diff -puN include/asm-sh64/ide.h~git-sh /dev/null --- a/include/asm-sh64/ide.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * linux/include/asm-sh64/ide.h - * - * Copyright (C) 1994-1996 Linus Torvalds & authors - * - * sh64 version by Richard Curnow & Paul Mundt - */ - -/* - * This file contains the sh64 architecture specific IDE code. - */ - -#ifndef __ASM_SH64_IDE_H -#define __ASM_SH64_IDE_H - -#ifdef __KERNEL__ - - -/* Without this, the initialisation of PCI IDE cards end up calling - * ide_init_hwif_ports, which won't work. */ -#ifdef CONFIG_BLK_DEV_IDEPCI -#define ide_default_io_ctl(base) (0) -#endif - -#include - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_IDE_H */ diff -puN include/asm-sh64/io.h~git-sh /dev/null --- a/include/asm-sh64/io.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef __ASM_SH64_IO_H -#define __ASM_SH64_IO_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/io.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ - -/* - * Convention: - * read{b,w,l}/write{b,w,l} are for PCI, - * while in{b,w,l}/out{b,w,l} are for ISA - * These may (will) be platform specific function. - * - * In addition, we have - * ctrl_in{b,w,l}/ctrl_out{b,w,l} for SuperH specific I/O. - * which are processor specific. Address should be the result of - * onchip_remap(); - */ - -#include -#include -#include -#include -#include - -/* - * Nothing overly special here.. instead of doing the same thing - * over and over again, we just define a set of sh64_in/out functions - * with an implicit size. The traditional read{b,w,l}/write{b,w,l} - * mess is wrapped to this, as are the SH-specific ctrl_in/out routines. - */ -static inline unsigned char sh64_in8(const volatile void __iomem *addr) -{ - return *(volatile unsigned char __force *)addr; -} - -static inline unsigned short sh64_in16(const volatile void __iomem *addr) -{ - return *(volatile unsigned short __force *)addr; -} - -static inline unsigned int sh64_in32(const volatile void __iomem *addr) -{ - return *(volatile unsigned int __force *)addr; -} - -static inline unsigned long long sh64_in64(const volatile void __iomem *addr) -{ - return *(volatile unsigned long long __force *)addr; -} - -static inline void sh64_out8(unsigned char b, volatile void __iomem *addr) -{ - *(volatile unsigned char __force *)addr = b; - wmb(); -} - -static inline void sh64_out16(unsigned short b, volatile void __iomem *addr) -{ - *(volatile unsigned short __force *)addr = b; - wmb(); -} - -static inline void sh64_out32(unsigned int b, volatile void __iomem *addr) -{ - *(volatile unsigned int __force *)addr = b; - wmb(); -} - -static inline void sh64_out64(unsigned long long b, volatile void __iomem *addr) -{ - *(volatile unsigned long long __force *)addr = b; - wmb(); -} - -#define readb(addr) sh64_in8(addr) -#define readw(addr) sh64_in16(addr) -#define readl(addr) sh64_in32(addr) -#define readb_relaxed(addr) sh64_in8(addr) -#define readw_relaxed(addr) sh64_in16(addr) -#define readl_relaxed(addr) sh64_in32(addr) - -#define writeb(b, addr) sh64_out8(b, addr) -#define writew(b, addr) sh64_out16(b, addr) -#define writel(b, addr) sh64_out32(b, addr) - -#define ctrl_inb(addr) sh64_in8(ioport_map(addr, 1)) -#define ctrl_inw(addr) sh64_in16(ioport_map(addr, 2)) -#define ctrl_inl(addr) sh64_in32(ioport_map(addr, 4)) - -#define ctrl_outb(b, addr) sh64_out8(b, ioport_map(addr, 1)) -#define ctrl_outw(b, addr) sh64_out16(b, ioport_map(addr, 2)) -#define ctrl_outl(b, addr) sh64_out32(b, ioport_map(addr, 4)) - -#define ioread8(addr) sh64_in8(addr) -#define ioread16(addr) sh64_in16(addr) -#define ioread32(addr) sh64_in32(addr) -#define iowrite8(b, addr) sh64_out8(b, addr) -#define iowrite16(b, addr) sh64_out16(b, addr) -#define iowrite32(b, addr) sh64_out32(b, addr) - -#define inb(addr) ctrl_inb(addr) -#define inw(addr) ctrl_inw(addr) -#define inl(addr) ctrl_inl(addr) -#define outb(b, addr) ctrl_outb(b, addr) -#define outw(b, addr) ctrl_outw(b, addr) -#define outl(b, addr) ctrl_outl(b, addr) - -void outsw(unsigned long port, const void *addr, unsigned long count); -void insw(unsigned long port, void *addr, unsigned long count); -void outsl(unsigned long port, const void *addr, unsigned long count); -void insl(unsigned long port, void *addr, unsigned long count); - -#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 __raw_readb readb -#define __raw_readw readw -#define __raw_readl readl -#define __raw_writeb writeb -#define __raw_writew writew -#define __raw_writel writel - -void memcpy_toio(void __iomem *to, const void *from, long count); -void memcpy_fromio(void *to, void __iomem *from, long count); - -#define mmiowb() - -#ifdef __KERNEL__ - -#ifdef CONFIG_SH_CAYMAN -extern unsigned long smsc_superio_virt; -#endif -#ifdef CONFIG_PCI -extern unsigned long pciio_virt; -#endif - -#define IO_SPACE_LIMIT 0xffffffff - -/* - * Change virtual addresses to physical addresses and vv. - * These are trivial on the 1:1 Linux/SuperH mapping - */ -static inline unsigned long virt_to_phys(volatile void * address) -{ - return __pa(address); -} - -static inline void * phys_to_virt(unsigned long address) -{ - return __va(address); -} - -extern void * __ioremap(unsigned long phys_addr, unsigned long size, - unsigned long flags); - -static inline void * ioremap(unsigned long phys_addr, unsigned long size) -{ - return __ioremap(phys_addr, size, 1); -} - -static inline void * ioremap_nocache (unsigned long phys_addr, unsigned long size) -{ - return __ioremap(phys_addr, size, 0); -} - -extern void iounmap(void *addr); - -unsigned long onchip_remap(unsigned long addr, unsigned long size, const char* name); -extern void onchip_unmap(unsigned long vaddr); - -/* - * 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_SH64_IO_H */ diff -puN include/asm-sh64/ioctl.h~git-sh /dev/null --- a/include/asm-sh64/ioctl.h +++ /dev/null @@ -1 +0,0 @@ -#include diff -puN include/asm-sh64/ioctls.h~git-sh /dev/null --- a/include/asm-sh64/ioctls.h +++ /dev/null @@ -1,116 +0,0 @@ -#ifndef __ASM_SH64_IOCTLS_H -#define __ASM_SH64_IOCTLS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/ioctls.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004 Richard Curnow - * - */ - -#include - -#define FIOCLEX 0x6601 /* _IO('f', 1) */ -#define FIONCLEX 0x6602 /* _IO('f', 2) */ -#define FIOASYNC 0x4004667d /* _IOW('f', 125, int) */ -#define FIONBIO 0x4004667e /* _IOW('f', 126, int) */ -#define FIONREAD 0x8004667f /* _IOW('f', 127, int) */ -#define TIOCINQ FIONREAD -#define FIOQSIZE 0x80086680 /* _IOR('f', 128, loff_t) */ - -#define TCGETS 0x5401 -#define TCSETS 0x5402 -#define TCSETSW 0x5403 -#define TCSETSF 0x5404 - -#define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */ -#define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */ -#define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */ -#define TCSETAF 0x4012741c /* _IOW('t', 28, struct termio) */ - -#define TCSBRK 0x741d /* _IO('t', 29) */ -#define TCXONC 0x741e /* _IO('t', 30) */ -#define TCFLSH 0x741f /* _IO('t', 31) */ - -#define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */ -#define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */ -#define TIOCSTART 0x746e /* _IO('t', 110) start output, like ^Q */ -#define TIOCSTOP 0x746f /* _IO('t', 111) stop output, like ^S */ -#define TIOCOUTQ 0x80047473 /* _IOR('t', 115, int) output queue size */ - -#define TIOCSPGRP 0x40047476 /* _IOW('t', 118, int) */ -#define TIOCGPGRP 0x80047477 /* _IOR('t', 119, int) */ - -#define TIOCEXCL 0x540c /* _IO('T', 12) */ -#define TIOCNXCL 0x540d /* _IO('T', 13) */ -#define TIOCSCTTY 0x540e /* _IO('T', 14) */ - -#define TIOCSTI 0x40015412 /* _IOW('T', 18, char) 0x5412 */ -#define TIOCMGET 0x80045415 /* _IOR('T', 21, unsigned int) 0x5415 */ -#define TIOCMBIS 0x40045416 /* _IOW('T', 22, unsigned int) 0x5416 */ -#define TIOCMBIC 0x40045417 /* _IOW('T', 23, unsigned int) 0x5417 */ -#define TIOCMSET 0x40045418 /* _IOW('T', 24, unsigned int) 0x5418 */ - -#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 TIOCGSOFTCAR 0x80045419 /* _IOR('T', 25, unsigned int) 0x5419 */ -#define TIOCSSOFTCAR 0x4004541a /* _IOW('T', 26, unsigned int) 0x541A */ -#define TIOCLINUX 0x4004541c /* _IOW('T', 28, char) 0x541C */ -#define TIOCCONS 0x541d /* _IO('T', 29) */ -#define TIOCGSERIAL 0x803c541e /* _IOR('T', 30, struct serial_struct) 0x541E */ -#define TIOCSSERIAL 0x403c541f /* _IOW('T', 31, struct serial_struct) 0x541F */ -#define TIOCPKT 0x40045420 /* _IOW('T', 32, int) 0x5420 */ - -#define TIOCPKT_DATA 0 -#define TIOCPKT_FLUSHREAD 1 -#define TIOCPKT_FLUSHWRITE 2 -#define TIOCPKT_STOP 4 -#define TIOCPKT_START 8 -#define TIOCPKT_NOSTOP 16 -#define TIOCPKT_DOSTOP 32 - - -#define TIOCNOTTY 0x5422 /* _IO('T', 34) */ -#define TIOCSETD 0x40045423 /* _IOW('T', 35, int) 0x5423 */ -#define TIOCGETD 0x80045424 /* _IOR('T', 36, int) 0x5424 */ -#define TCSBRKP 0x40045424 /* _IOW('T', 37, int) 0x5425 */ /* Needed for POSIX tcsendbreak() */ -#define TIOCTTYGSTRUCT 0x8c105426 /* _IOR('T', 38, struct tty_struct) 0x5426 */ /* For debugging only */ -#define TIOCSBRK 0x5427 /* _IO('T', 39) */ /* BSD compatibility */ -#define TIOCCBRK 0x5428 /* _IO('T', 40) */ /* BSD compatibility */ -#define TIOCGSID 0x80045429 /* _IOR('T', 41, pid_t) 0x5429 */ /* Return the session ID of FD */ -#define TIOCGPTN 0x80045430 /* _IOR('T',0x30, unsigned int) 0x5430 Get Pty Number (of pty-mux device) */ -#define TIOCSPTLCK 0x40045431 /* _IOW('T',0x31, int) Lock/unlock Pty */ - -#define TIOCSERCONFIG 0x5453 /* _IO('T', 83) */ -#define TIOCSERGWILD 0x80045454 /* _IOR('T', 84, int) 0x5454 */ -#define TIOCSERSWILD 0x40045455 /* _IOW('T', 85, int) 0x5455 */ -#define TIOCGLCKTRMIOS 0x5456 -#define TIOCSLCKTRMIOS 0x5457 -#define TIOCSERGSTRUCT 0x80d85458 /* _IOR('T', 88, struct async_struct) 0x5458 */ /* For debugging only */ -#define TIOCSERGETLSR 0x80045459 /* _IOR('T', 89, unsigned int) 0x5459 */ /* Get line status register */ - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ -#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ - -#define TIOCSERGETMULTI 0x80a8545a /* _IOR('T', 90, struct serial_multiport_struct) 0x545A */ /* Get multiport config */ -#define TIOCSERSETMULTI 0x40a8545b /* _IOW('T', 91, struct serial_multiport_struct) 0x545B */ /* Set multiport config */ - -#define TIOCMIWAIT 0x545c /* _IO('T', 92) wait for a change on serial input line(s) */ -#define TIOCGICOUNT 0x545d /* read serial port inline interrupt counts */ - -#endif /* __ASM_SH64_IOCTLS_H */ diff -puN include/asm-sh64/ipcbuf.h~git-sh /dev/null --- a/include/asm-sh64/ipcbuf.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __ASM_SH64_IPCBUF_H__ -#define __ASM_SH64_IPCBUF_H__ - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/ipcbuf.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * The ipc64_perm structure for i386 architecture. - * Note extra padding because this structure is passed back and forth - * between kernel and user space. - * - * Pad space is left for: - * - 32-bit mode_t and seq - * - 2 miscellaneous 32-bit values - */ - -struct ipc64_perm -{ - __kernel_key_t key; - __kernel_uid32_t uid; - __kernel_gid32_t gid; - __kernel_uid32_t cuid; - __kernel_gid32_t cgid; - __kernel_mode_t mode; - unsigned short __pad1; - unsigned short seq; - unsigned short __pad2; - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* __ASM_SH64_IPCBUF_H__ */ diff -puN include/asm-sh64/irq.h~git-sh /dev/null --- a/include/asm-sh64/irq.h +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef __ASM_SH64_IRQ_H -#define __ASM_SH64_IRQ_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/irq.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - - -/* - * Encoded IRQs are not considered worth to be supported. - * Main reason is that there's no per-encoded-interrupt - * enable/disable mechanism (as there was in SH3/4). - * An all enabled/all disabled is worth only if there's - * a cascaded IC to disable/enable/ack on. Until such - * IC is available there's no such support. - * - * Presumably Encoded IRQs may use extra IRQs beyond 64, - * below. Some logic must be added to cope with IRQ_IRL? - * in an exclusive way. - * - * Priorities are set at Platform level, when IRQ_IRL0-3 - * are set to 0 Encoding is allowed. Otherwise it's not - * allowed. - */ - -/* Independent IRQs */ -#define IRQ_IRL0 0 -#define IRQ_IRL1 1 -#define IRQ_IRL2 2 -#define IRQ_IRL3 3 - -#define IRQ_INTA 4 -#define IRQ_INTB 5 -#define IRQ_INTC 6 -#define IRQ_INTD 7 - -#define IRQ_SERR 12 -#define IRQ_ERR 13 -#define IRQ_PWR3 14 -#define IRQ_PWR2 15 -#define IRQ_PWR1 16 -#define IRQ_PWR0 17 - -#define IRQ_DMTE0 18 -#define IRQ_DMTE1 19 -#define IRQ_DMTE2 20 -#define IRQ_DMTE3 21 -#define IRQ_DAERR 22 - -#define IRQ_TUNI0 32 -#define IRQ_TUNI1 33 -#define IRQ_TUNI2 34 -#define IRQ_TICPI2 35 - -#define IRQ_ATI 36 -#define IRQ_PRI 37 -#define IRQ_CUI 38 - -#define IRQ_ERI 39 -#define IRQ_RXI 40 -#define IRQ_BRI 41 -#define IRQ_TXI 42 - -#define IRQ_ITI 63 - -#define NR_INTC_IRQS 64 - -#ifdef CONFIG_SH_CAYMAN -#define NR_EXT_IRQS 32 -#define START_EXT_IRQS 64 - -/* PCI bus 2 uses encoded external interrupts on the Cayman board */ -#define IRQ_P2INTA (START_EXT_IRQS + (3*8) + 0) -#define IRQ_P2INTB (START_EXT_IRQS + (3*8) + 1) -#define IRQ_P2INTC (START_EXT_IRQS + (3*8) + 2) -#define IRQ_P2INTD (START_EXT_IRQS + (3*8) + 3) - -#define I8042_KBD_IRQ (START_EXT_IRQS + 2) -#define I8042_AUX_IRQ (START_EXT_IRQS + 6) - -#define IRQ_CFCARD (START_EXT_IRQS + 7) -#define IRQ_PCMCIA (0) - -#else -#define NR_EXT_IRQS 0 -#endif - -#define NR_IRQS (NR_INTC_IRQS+NR_EXT_IRQS) - - -/* Default IRQs, fixed */ -#define TIMER_IRQ IRQ_TUNI0 -#define RTC_IRQ IRQ_CUI - -/* Default Priorities, Platform may choose differently */ -#define NO_PRIORITY 0 /* Disabled */ -#define TIMER_PRIORITY 2 -#define RTC_PRIORITY TIMER_PRIORITY -#define SCIF_PRIORITY 3 -#define INTD_PRIORITY 3 -#define IRL3_PRIORITY 4 -#define INTC_PRIORITY 6 -#define IRL2_PRIORITY 7 -#define INTB_PRIORITY 9 -#define IRL1_PRIORITY 10 -#define INTA_PRIORITY 12 -#define IRL0_PRIORITY 13 -#define TOP_PRIORITY 15 - -extern int intc_evt_to_irq[(0xE20/0x20)+1]; -int intc_irq_describe(char* p, int irq); - -#define irq_canonicalize(irq) (irq) - -#ifdef CONFIG_SH_CAYMAN -int cayman_irq_demux(int evt); -int cayman_irq_describe(char* p, int irq); -#define irq_demux(x) cayman_irq_demux(x) -#define irq_describe(p, x) cayman_irq_describe(p, x) -#else -#define irq_demux(x) (intc_evt_to_irq[x]) -#define irq_describe(p, x) intc_irq_describe(p, x) -#endif - -/* - * Function for "on chip support modules". - */ - -/* - * SH-5 supports Priority based interrupts only. - * Interrupt priorities are defined at platform level. - */ -#define set_ipr_data(a, b, c, d) -#define make_ipr_irq(a) -#define make_imask_irq(a) - -#endif /* __ASM_SH64_IRQ_H */ diff -puN include/asm-sh64/irq_regs.h~git-sh /dev/null --- a/include/asm-sh64/irq_regs.h +++ /dev/null @@ -1 +0,0 @@ -#include diff -puN include/asm-sh64/kdebug.h~git-sh /dev/null --- a/include/asm-sh64/kdebug.h +++ /dev/null @@ -1 +0,0 @@ -#include diff -puN include/asm-sh64/keyboard.h~git-sh /dev/null --- a/include/asm-sh64/keyboard.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * linux/include/asm-shmedia/keyboard.h - * - * Copied from i386 version: - * Created 3 Nov 1996 by Geert Uytterhoeven - */ - -/* - * This file contains the i386 architecture specific keyboard definitions - */ - -#ifndef __ASM_SH64_KEYBOARD_H -#define __ASM_SH64_KEYBOARD_H - -#ifdef __KERNEL__ - -#include -#include -#include - -#ifdef CONFIG_SH_CAYMAN -#define KEYBOARD_IRQ (START_EXT_IRQS + 2) /* SMSC SuperIO IRQ 1 */ -#endif -#define DISABLE_KBD_DURING_INTERRUPTS 0 - -extern int pckbd_setkeycode(unsigned int scancode, unsigned int keycode); -extern int pckbd_getkeycode(unsigned int scancode); -extern int pckbd_translate(unsigned char scancode, unsigned char *keycode, - char raw_mode); -extern char pckbd_unexpected_up(unsigned char keycode); -extern void pckbd_leds(unsigned char leds); -extern void pckbd_init_hw(void); - -#define kbd_setkeycode pckbd_setkeycode -#define kbd_getkeycode pckbd_getkeycode -#define kbd_translate pckbd_translate -#define kbd_unexpected_up pckbd_unexpected_up -#define kbd_leds pckbd_leds -#define kbd_init_hw pckbd_init_hw - -/* resource allocation */ -#define kbd_request_region() -#define kbd_request_irq(handler) request_irq(KEYBOARD_IRQ, handler, 0, \ - "keyboard", NULL) - -/* How to access the keyboard macros on this platform. */ -#define kbd_read_input() inb(KBD_DATA_REG) -#define kbd_read_status() inb(KBD_STATUS_REG) -#define kbd_write_output(val) outb(val, KBD_DATA_REG) -#define kbd_write_command(val) outb(val, KBD_CNTL_REG) - -/* Some stoneage hardware needs delays after some operations. */ -#define kbd_pause() do { } while(0) - -/* - * Machine specific bits for the PS/2 driver - */ - -#ifdef CONFIG_SH_CAYMAN -#define AUX_IRQ (START_EXT_IRQS + 6) /* SMSC SuperIO IRQ12 */ -#endif - -#define aux_request_irq(hand, dev_id) \ - request_irq(AUX_IRQ, hand, IRQF_SHARED, "PS2 Mouse", dev_id) - -#define aux_free_irq(dev_id) free_irq(AUX_IRQ, dev_id) - -#endif /* __KERNEL__ */ -#endif /* __ASM_SH64_KEYBOARD_H */ - diff -puN include/asm-sh64/kmap_types.h~git-sh /dev/null --- a/include/asm-sh64/kmap_types.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH64_KMAP_TYPES_H -#define __ASM_SH64_KMAP_TYPES_H - -#include - -#endif /* __ASM_SH64_KMAP_TYPES_H */ - diff -puN include/asm-sh64/linkage.h~git-sh /dev/null --- a/include/asm-sh64/linkage.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH64_LINKAGE_H -#define __ASM_SH64_LINKAGE_H - -#include - -#endif /* __ASM_SH64_LINKAGE_H */ - diff -puN include/asm-sh64/local.h~git-sh /dev/null --- a/include/asm-sh64/local.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH64_LOCAL_H -#define __ASM_SH64_LOCAL_H - -#include - -#endif /* __ASM_SH64_LOCAL_H */ - diff -puN include/asm-sh64/mc146818rtc.h~git-sh /dev/null --- a/include/asm-sh64/mc146818rtc.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * linux/include/asm-sh64/mc146818rtc.h - * -*/ - -/* For now, an empty place-holder to get IDE to compile. */ - diff -puN include/asm-sh64/mman.h~git-sh /dev/null --- a/include/asm-sh64/mman.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_MMAN_H -#define __ASM_SH64_MMAN_H - -#include - -#endif /* __ASM_SH64_MMAN_H */ diff -puN include/asm-sh64/mmu.h~git-sh /dev/null --- a/include/asm-sh64/mmu.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __MMU_H -#define __MMU_H - -/* Default "unsigned long" context */ -typedef unsigned long mm_context_t; - -#endif diff -puN include/asm-sh64/mmu_context.h~git-sh /dev/null --- a/include/asm-sh64/mmu_context.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef __ASM_SH64_MMU_CONTEXT_H -#define __ASM_SH64_MMU_CONTEXT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/mmu_context.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * ASID handling idea taken from MIPS implementation. - * - */ - -#ifndef __ASSEMBLY__ - -/* - * Cache of MMU context last used. - * - * The MMU "context" consists of two things: - * (a) TLB cache version (or cycle, top 24 bits of mmu_context_cache) - * (b) ASID (Address Space IDentifier, bottom 8 bits of mmu_context_cache) - */ -extern unsigned long mmu_context_cache; - -#include -#include - -/* Current mm's pgd */ -extern pgd_t *mmu_pdtp_cache; - -#define SR_ASID_MASK 0xffffffffff00ffffULL -#define SR_ASID_SHIFT 16 - -#define MMU_CONTEXT_ASID_MASK 0x000000ff -#define MMU_CONTEXT_VERSION_MASK 0xffffff00 -#define MMU_CONTEXT_FIRST_VERSION 0x00000100 -#define NO_CONTEXT 0 - -/* ASID is 8-bit value, so it can't be 0x100 */ -#define MMU_NO_ASID 0x100 - - -/* - * Virtual Page Number mask - */ -#define MMU_VPN_MASK 0xfffff000 - -static inline void -get_new_mmu_context(struct mm_struct *mm) -{ - extern void flush_tlb_all(void); - extern void flush_cache_all(void); - - unsigned long mc = ++mmu_context_cache; - - if (!(mc & MMU_CONTEXT_ASID_MASK)) { - /* We exhaust ASID of this version. - Flush all TLB and start new cycle. */ - flush_tlb_all(); - /* We have to flush all caches as ASIDs are - used in cache */ - flush_cache_all(); - /* Fix version if needed. - Note that we avoid version #0/asid #0 to distingush NO_CONTEXT. */ - if (!mc) - mmu_context_cache = mc = MMU_CONTEXT_FIRST_VERSION; - } - mm->context = mc; -} - -/* - * Get MMU context if needed. - */ -static __inline__ void -get_mmu_context(struct mm_struct *mm) -{ - if (mm) { - unsigned long mc = mmu_context_cache; - /* Check if we have old version of context. - If it's old, we need to get new context with new version. */ - if ((mm->context ^ mc) & MMU_CONTEXT_VERSION_MASK) - get_new_mmu_context(mm); - } -} - -/* - * Initialize the context related info for a new mm_struct - * instance. - */ -static inline int init_new_context(struct task_struct *tsk, - struct mm_struct *mm) -{ - mm->context = NO_CONTEXT; - - return 0; -} - -/* - * Destroy context related info for an mm_struct that is about - * to be put to rest. - */ -static inline void destroy_context(struct mm_struct *mm) -{ - extern void flush_tlb_mm(struct mm_struct *mm); - - /* Well, at least free TLB entries */ - flush_tlb_mm(mm); -} - -#endif /* __ASSEMBLY__ */ - -/* Common defines */ -#define TLB_STEP 0x00000010 -#define TLB_PTEH 0x00000000 -#define TLB_PTEL 0x00000008 - -/* PTEH defines */ -#define PTEH_ASID_SHIFT 2 -#define PTEH_VALID 0x0000000000000001 -#define PTEH_SHARED 0x0000000000000002 -#define PTEH_MATCH_ASID 0x00000000000003ff - -#ifndef __ASSEMBLY__ -/* This has to be a common function because the next location to fill - * information is shared. */ -extern void __do_tlb_refill(unsigned long address, unsigned long long is_text_not_data, pte_t *pte); - -/* Profiling counter. */ -#ifdef CONFIG_SH64_PROC_TLB -extern unsigned long long calls_to_do_fast_page_fault; -#endif - -static inline unsigned long get_asid(void) -{ - unsigned long long sr; - - asm volatile ("getcon " __SR ", %0\n\t" - : "=r" (sr)); - - sr = (sr >> SR_ASID_SHIFT) & MMU_CONTEXT_ASID_MASK; - return (unsigned long) sr; -} - -/* Set ASID into SR */ -static inline void set_asid(unsigned long asid) -{ - unsigned long long sr, pc; - - asm volatile ("getcon " __SR ", %0" : "=r" (sr)); - - sr = (sr & SR_ASID_MASK) | (asid << SR_ASID_SHIFT); - - /* - * It is possible that this function may be inlined and so to avoid - * the assembler reporting duplicate symbols we make use of the gas trick - * of generating symbols using numerics and forward reference. - */ - asm volatile ("movi 1, %1\n\t" - "shlli %1, 28, %1\n\t" - "or %0, %1, %1\n\t" - "putcon %1, " __SR "\n\t" - "putcon %0, " __SSR "\n\t" - "movi 1f, %1\n\t" - "ori %1, 1 , %1\n\t" - "putcon %1, " __SPC "\n\t" - "rte\n" - "1:\n\t" - : "=r" (sr), "=r" (pc) : "0" (sr)); -} - -/* - * After we have set current->mm to a new value, this activates - * the context for the new mm so we see the new mappings. - */ -static __inline__ void activate_context(struct mm_struct *mm) -{ - get_mmu_context(mm); - set_asid(mm->context & MMU_CONTEXT_ASID_MASK); -} - - -static __inline__ void switch_mm(struct mm_struct *prev, - struct mm_struct *next, - struct task_struct *tsk) -{ - if (prev != next) { - mmu_pdtp_cache = next->pgd; - activate_context(next); - } -} - -#define deactivate_mm(tsk,mm) do { } while (0) - -#define activate_mm(prev, next) \ - switch_mm((prev),(next),NULL) - -static inline void -enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) -{ -} - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_SH64_MMU_CONTEXT_H */ diff -puN include/asm-sh64/module.h~git-sh /dev/null --- a/include/asm-sh64/module.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __ASM_SH64_MODULE_H -#define __ASM_SH64_MODULE_H -/* - * This file contains the SH architecture specific module code. - */ - -struct mod_arch_specific { - /* empty */ -}; - -#define Elf_Shdr Elf32_Shdr -#define Elf_Sym Elf32_Sym -#define Elf_Ehdr Elf32_Ehdr - -#define module_map(x) vmalloc(x) -#define module_unmap(x) vfree(x) -#define module_arch_init(x) (0) -#define arch_init_modules(x) do { } while (0) - -#endif /* __ASM_SH64_MODULE_H */ diff -puN include/asm-sh64/msgbuf.h~git-sh /dev/null --- a/include/asm-sh64/msgbuf.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __ASM_SH64_MSGBUF_H -#define __ASM_SH64_MSGBUF_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/msgbuf.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * The msqid64_ds structure for i386 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_SH64_MSGBUF_H */ diff -puN include/asm-sh64/mutex.h~git-sh /dev/null --- a/include/asm-sh64/mutex.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Pull in the generic implementation for the mutex fastpath. - * - * TODO: implement optimized primitives instead, or leave the generic - * implementation in place, or pick the atomic_xchg() based generic - * implementation. (see asm-generic/mutex-xchg.h for details) - */ - -#include diff -puN include/asm-sh64/namei.h~git-sh /dev/null --- a/include/asm-sh64/namei.h +++ /dev/null @@ -1,24 +0,0 @@ -#ifndef __ASM_SH64_NAMEI_H -#define __ASM_SH64_NAMEI_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/namei.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * Included from linux/fs/namei.c - * - */ - -/* This dummy routine maybe changed to something useful - * for /usr/gnemul/ emulation stuff. - * Look at asm-sparc/namei.h for details. - */ - -#define __emul_prefix() NULL - -#endif /* __ASM_SH64_NAMEI_H */ diff -puN include/asm-sh64/page.h~git-sh /dev/null --- a/include/asm-sh64/page.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __ASM_SH64_PAGE_H -#define __ASM_SH64_PAGE_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/page.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * benedict.gaster@superh.com 19th, 24th July 2002. - * - * Modified to take account of enabling for D-CACHE support. - * - */ - - -/* PAGE_SHIFT determines the page size */ -#define PAGE_SHIFT 12 -#ifdef __ASSEMBLY__ -#define PAGE_SIZE 4096 -#else -#define PAGE_SIZE (1UL << PAGE_SHIFT) -#endif -#define PAGE_MASK (~(PAGE_SIZE-1)) -#define PTE_MASK PAGE_MASK - -#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -#define HPAGE_SHIFT 16 -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -#define HPAGE_SHIFT 20 -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512MB) -#define HPAGE_SHIFT 29 -#endif - -#ifdef CONFIG_HUGETLB_PAGE -#define HPAGE_SIZE (1UL << HPAGE_SHIFT) -#define HPAGE_MASK (~(HPAGE_SIZE-1)) -#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT) -#define ARCH_HAS_SETCLEAR_HUGE_PTE -#endif - -#ifdef __KERNEL__ -#ifndef __ASSEMBLY__ - -extern struct page *mem_map; -extern void sh64_page_clear(void *page); -extern void sh64_page_copy(void *from, void *to); - -#define clear_page(page) sh64_page_clear(page) -#define copy_page(to,from) sh64_page_copy(from, to) - -#if defined(CONFIG_DCACHE_DISABLED) - -#define clear_user_page(page, vaddr, pg) clear_page(page) -#define copy_user_page(to, from, vaddr, pg) copy_page(to, from) - -#else - -extern void clear_user_page(void *to, unsigned long address, struct page *pg); -extern void copy_user_page(void *to, void *from, unsigned long address, struct page *pg); - -#endif /* defined(CONFIG_DCACHE_DISABLED) */ - -/* - * These are used to make use of C type-checking.. - */ -typedef struct { unsigned long long pte; } pte_t; -typedef struct { unsigned long pmd; } pmd_t; -typedef struct { unsigned long pgd; } pgd_t; -typedef struct { unsigned long pgprot; } pgprot_t; - -#define pte_val(x) ((x).pte) -#define pmd_val(x) ((x).pmd) -#define pgd_val(x) ((x).pgd) -#define pgprot_val(x) ((x).pgprot) - -#define __pte(x) ((pte_t) { (x) } ) -#define __pmd(x) ((pmd_t) { (x) } ) -#define __pgd(x) ((pgd_t) { (x) } ) -#define __pgprot(x) ((pgprot_t) { (x) } ) - -#endif /* !__ASSEMBLY__ */ - -/* to align the pointer to the (next) page boundary */ -#define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK) - -/* - * Kconfig defined. - */ -#define __MEMORY_START (CONFIG_MEMORY_START) -#define PAGE_OFFSET (CONFIG_CACHED_MEMORY_OFFSET) - -#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET) -#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) -#define MAP_NR(addr) ((__pa(addr)-__MEMORY_START) >> PAGE_SHIFT) -#define VALID_PAGE(page) ((page - mem_map) < max_mapnr) - -#define phys_to_page(phys) (mem_map + (((phys) - __MEMORY_START) >> PAGE_SHIFT)) -#define page_to_phys(page) (((page - mem_map) << PAGE_SHIFT) + __MEMORY_START) - -/* PFN start number, because of __MEMORY_START */ -#define PFN_START (__MEMORY_START >> PAGE_SHIFT) -#define ARCH_PFN_OFFSET (PFN_START) -#define virt_to_page(kaddr) pfn_to_page(__pa(kaddr) >> PAGE_SHIFT) -#define pfn_valid(pfn) (((pfn) - PFN_START) < max_mapnr) -#define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) - -#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -#include -#include - -#endif /* __KERNEL__ */ -#endif /* __ASM_SH64_PAGE_H */ diff -puN include/asm-sh64/param.h~git-sh /dev/null --- a/include/asm-sh64/param.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/param.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - */ -#ifndef __ASM_SH64_PARAM_H -#define __ASM_SH64_PARAM_H - - -#ifdef __KERNEL__ -# ifdef CONFIG_SH_WDT -# define HZ 1000 /* Needed for high-res WOVF */ -# else -# define HZ 100 -# endif -# define USER_HZ 100 /* User interfaces are in "ticks" */ -# define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ -#endif - -#ifndef HZ -#define HZ 100 -#endif - -#define EXEC_PAGESIZE 4096 - -#ifndef NGROUPS -#define NGROUPS 32 -#endif - -#ifndef NOGROUP -#define NOGROUP (-1) -#endif - -#define MAXHOSTNAMELEN 64 /* max length of hostname */ - -#endif /* __ASM_SH64_PARAM_H */ diff -puN include/asm-sh64/pci.h~git-sh /dev/null --- a/include/asm-sh64/pci.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef __ASM_SH64_PCI_H -#define __ASM_SH64_PCI_H - -#ifdef __KERNEL__ - -#include - -/* Can be used to override the logic in pci_scan_bus for skipping - already-configured bus numbers - to be used for buggy BIOSes - or architectures with incomplete PCI setup by the loader */ - -#define pcibios_assign_all_busses() 1 - -/* - * These are currently the correct values for the STM overdrive board - * We need some way of setting this on a board specific way, it will - * not be the same on other boards I think - */ -#if defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) -#define PCIBIOS_MIN_IO 0x2000 -#define PCIBIOS_MIN_MEM 0x40000000 -#endif - -extern void pcibios_set_master(struct pci_dev *dev); - -/* - * Set penalize isa irq function - */ -static inline void pcibios_penalize_isa_irq(int irq, int active) -{ - /* We don't do dynamic PCI IRQ allocation */ -} - -/* Dynamic DMA mapping stuff. - * SuperH has everything mapped statically like x86. - */ - -/* The PCI address space does equal the physical memory - * address space. The networking and block device layers use - * this boolean for bounce buffer decisions. - */ -#define PCI_DMA_BUS_IS_PHYS (1) - -#include -#include -#include -#include -#include - -/* pci_unmap_{single,page} being a nop depends upon the - * configuration. - */ -#ifdef CONFIG_SH_PCIDMA_NONCOHERENT -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \ - dma_addr_t ADDR_NAME; -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) \ - __u32 LEN_NAME; -#define pci_unmap_addr(PTR, ADDR_NAME) \ - ((PTR)->ADDR_NAME) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) \ - (((PTR)->ADDR_NAME) = (VAL)) -#define pci_unmap_len(PTR, LEN_NAME) \ - ((PTR)->LEN_NAME) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \ - (((PTR)->LEN_NAME) = (VAL)) -#else -#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) -#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) -#define pci_unmap_addr(PTR, ADDR_NAME) (0) -#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) do { } while (0) -#define pci_unmap_len(PTR, LEN_NAME) (0) -#define pci_unmap_len_set(PTR, LEN_NAME, VAL) do { } while (0) -#endif - -#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 - -/* Board-specific fixup routines. */ -extern void pcibios_fixup(void); -extern void pcibios_fixup_irqs(void); - -#ifdef CONFIG_PCI_AUTO -extern int pciauto_assign_resources(int busno, struct pci_channel *hose); -#endif - -#endif /* __KERNEL__ */ - -/* generic pci stuff */ -#include - -/* generic DMA-mapping stuff */ -#include - -#endif /* __ASM_SH64_PCI_H */ - diff -puN include/asm-sh64/percpu.h~git-sh /dev/null --- a/include/asm-sh64/percpu.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_PERCPU -#define __ASM_SH64_PERCPU - -#include - -#endif /* __ASM_SH64_PERCPU */ diff -puN include/asm-sh64/pgalloc.h~git-sh /dev/null --- a/include/asm-sh64/pgalloc.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef __ASM_SH64_PGALLOC_H -#define __ASM_SH64_PGALLOC_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/pgalloc.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - */ - -#include -#include -#include - -static inline void pgd_init(unsigned long page) -{ - unsigned long *pgd = (unsigned long *)page; - extern pte_t empty_bad_pte_table[PTRS_PER_PTE]; - int i; - - for (i = 0; i < USER_PTRS_PER_PGD; i++) - pgd[i] = (unsigned long)empty_bad_pte_table; -} - -/* - * Allocate and free page tables. The xxx_kernel() versions are - * used to allocate a kernel page table - this turns on ASN bits - * if any. - */ - -static inline pgd_t *get_pgd_slow(void) -{ - unsigned int pgd_size = (USER_PTRS_PER_PGD * sizeof(pgd_t)); - pgd_t *ret = kmalloc(pgd_size, GFP_KERNEL); - return ret; -} - -static inline pgd_t *pgd_alloc(struct mm_struct *mm) -{ - return quicklist_alloc(0, GFP_KERNEL, NULL); -} - -static inline void pgd_free(pgd_t *pgd) -{ - quicklist_free(0, NULL, pgd); -} - -static inline struct page *pte_alloc_one(struct mm_struct *mm, - unsigned long address) -{ - void *pg = quicklist_alloc(0, GFP_KERNEL, NULL); - return pg ? virt_to_page(pg) : NULL; -} - -static inline void pte_free_kernel(pte_t *pte) -{ - quicklist_free(0, NULL, pte); -} - -static inline void pte_free(struct page *pte) -{ - quicklist_free_page(0, NULL, pte); -} - -static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, - unsigned long address) -{ - return quicklist_alloc(0, GFP_KERNEL, NULL); -} - -#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) - -/* - * allocating and freeing a pmd is trivial: the 1-entry pmd is - * inside the pgd, so has no extra memory associated with it. - */ - -#if defined(CONFIG_SH64_PGTABLE_2_LEVEL) - -#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); }) -#define pmd_free(x) do { } while (0) -#define pgd_populate(mm, pmd, pte) BUG() -#define __pte_free_tlb(tlb,pte) tlb_remove_page((tlb),(pte)) -#define __pmd_free_tlb(tlb,pmd) do { } while (0) - -#elif defined(CONFIG_SH64_PGTABLE_3_LEVEL) - -static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) -{ - return quicklist_alloc(0, GFP_KERNEL, NULL); -} - -static inline void pmd_free(pmd_t *pmd) -{ - quicklist_free(0, NULL, pmd); -} - -#define pgd_populate(mm, pgd, pmd) pgd_set(pgd, pmd) -#define __pmd_free_tlb(tlb,pmd) pmd_free(pmd) - -#else -#error "No defined page table size" -#endif - -#define pmd_populate_kernel(mm, pmd, pte) \ - set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) (pte))) - -static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, - struct page *pte) -{ - set_pmd(pmd, __pmd(_PAGE_TABLE + (unsigned long) page_address (pte))); -} - -static inline void check_pgt_cache(void) -{ - quicklist_trim(0, NULL, 25, 16); -} - -#endif /* __ASM_SH64_PGALLOC_H */ diff -puN include/asm-sh64/pgtable.h~git-sh /dev/null --- a/include/asm-sh64/pgtable.h +++ /dev/null @@ -1,496 +0,0 @@ -#ifndef __ASM_SH64_PGTABLE_H -#define __ASM_SH64_PGTABLE_H - -#include - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/pgtable.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * Copyright (C) 2003, 2004 Richard Curnow - * - * This file contains the functions and defines necessary to modify and use - * the SuperH page table tree. - */ - -#ifndef __ASSEMBLY__ -#include -#include -#include - -struct vm_area_struct; - -extern void paging_init(void); - -/* We provide our own get_unmapped_area to avoid cache synonym issue */ -#define HAVE_ARCH_UNMAPPED_AREA - -/* - * Basically we have the same two-level (which is the logical three level - * Linux page table layout folded) page tables as the i386. - */ - -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -extern unsigned char empty_zero_page[PAGE_SIZE]; -#define ZERO_PAGE(vaddr) (mem_map + MAP_NR(empty_zero_page)) - -#endif /* !__ASSEMBLY__ */ - -/* - * NEFF and NPHYS related defines. - * FIXME : These need to be model-dependent. For now this is OK, SH5-101 and SH5-103 - * implement 32 bits effective and 32 bits physical. But future implementations may - * extend beyond this. - */ -#define NEFF 32 -#define NEFF_SIGN (1LL << (NEFF - 1)) -#define NEFF_MASK (-1LL << NEFF) - -#define NPHYS 32 -#define NPHYS_SIGN (1LL << (NPHYS - 1)) -#define NPHYS_MASK (-1LL << NPHYS) - -/* Typically 2-level is sufficient up to 32 bits of virtual address space, beyond - that 3-level would be appropriate. */ -#if defined(CONFIG_SH64_PGTABLE_2_LEVEL) -/* For 4k pages, this contains 512 entries, i.e. 9 bits worth of address. */ -#define PTRS_PER_PTE ((1<> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) -#define __pgd_offset(address) pgd_index(address) -#define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) - -/* To find an entry in a kernel PGD. */ -#define pgd_offset_k(address) pgd_offset(&init_mm, address) - -/* - * PGD level access routines. - * - * Note1: - * There's no need to use physical addresses since the tree walk is all - * in performed in software, until the PTE translation. - * - * Note 2: - * A PGD entry can be uninitialized (_PGD_UNUSED), generically bad, - * clear (_PGD_EMPTY), present. When present, lower 3 nibbles contain - * _KERNPG_TABLE. Being a kernel virtual pointer also bit 31 must - * be 1. Assuming an arbitrary clear value of bit 31 set to 0 and - * lower 3 nibbles set to 0xFFF (_PGD_EMPTY) any other value is a - * bad pgd that must be notified via printk(). - * - */ -#define _PGD_EMPTY 0x0 - -#if defined(CONFIG_SH64_PGTABLE_2_LEVEL) -static inline int pgd_none(pgd_t pgd) { return 0; } -static inline int pgd_bad(pgd_t pgd) { return 0; } -#define pgd_present(pgd) ((pgd_val(pgd) & _PAGE_PRESENT) ? 1 : 0) -#define pgd_clear(xx) do { } while(0) - -#elif defined(CONFIG_SH64_PGTABLE_3_LEVEL) -#define pgd_present(pgd_entry) (1) -#define pgd_none(pgd_entry) (pgd_val((pgd_entry)) == _PGD_EMPTY) -/* TODO: Think later about what a useful definition of 'bad' would be now. */ -#define pgd_bad(pgd_entry) (0) -#define pgd_clear(pgd_entry_p) (set_pgd((pgd_entry_p), __pgd(_PGD_EMPTY))) - -#endif - - -#define pgd_page_vaddr(pgd_entry) ((unsigned long) (pgd_val(pgd_entry) & PAGE_MASK)) -#define pgd_page(pgd) (virt_to_page(pgd_val(pgd))) - - -/* - * PMD defines. Middle level. - */ - -/* PGD to PMD dereferencing */ -#if defined(CONFIG_SH64_PGTABLE_2_LEVEL) -static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) -{ - return (pmd_t *) dir; -} -#elif defined(CONFIG_SH64_PGTABLE_3_LEVEL) -#define __pmd_offset(address) \ - (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1)) -#define pmd_offset(dir, addr) \ - ((pmd_t *) ((pgd_val(*(dir))) & PAGE_MASK) + __pmd_offset((addr))) -#endif - -/* - * PMD level access routines. Same notes as above. - */ -#define _PMD_EMPTY 0x0 -/* Either the PMD is empty or present, it's not paged out */ -#define pmd_present(pmd_entry) (pmd_val(pmd_entry) & _PAGE_PRESENT) -#define pmd_clear(pmd_entry_p) (set_pmd((pmd_entry_p), __pmd(_PMD_EMPTY))) -#define pmd_none(pmd_entry) (pmd_val((pmd_entry)) == _PMD_EMPTY) -#define pmd_bad(pmd_entry) ((pmd_val(pmd_entry) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE) - -#define pmd_page_vaddr(pmd_entry) \ - ((unsigned long) __va(pmd_val(pmd_entry) & PAGE_MASK)) - -#define pmd_page(pmd) \ - (virt_to_page(pmd_val(pmd))) - -/* PMD to PTE dereferencing */ -#define pte_index(address) \ - ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)) - -#define pte_offset_kernel(dir, addr) \ - ((pte_t *) ((pmd_val(*(dir))) & PAGE_MASK) + pte_index((addr))) - -#define pte_offset_map(dir,addr) pte_offset_kernel(dir, addr) -#define pte_offset_map_nested(dir,addr) pte_offset_kernel(dir, addr) -#define pte_unmap(pte) do { } while (0) -#define pte_unmap_nested(pte) do { } while (0) - -/* Round it up ! */ -#define USER_PTRS_PER_PGD ((TASK_SIZE+PGDIR_SIZE-1)/PGDIR_SIZE) -#define FIRST_USER_ADDRESS 0 - -#ifndef __ASSEMBLY__ -#define VMALLOC_END 0xff000000 -#define VMALLOC_START 0xf0000000 -#define VMALLOC_VMADDR(x) ((unsigned long)(x)) - -#define IOBASE_VADDR 0xff000000 -#define IOBASE_END 0xffffffff - -/* - * PTEL coherent flags. - * See Chapter 17 ST50 CPU Core Volume 1, Architecture. - */ -/* The bits that are required in the SH-5 TLB are placed in the h/w-defined - positions, to avoid expensive bit shuffling on every refill. The remaining - bits are used for s/w purposes and masked out on each refill. - - Note, the PTE slots are used to hold data of type swp_entry_t when a page is - swapped out. Only the _PAGE_PRESENT flag is significant when the page is - swapped out, and it must be placed so that it doesn't overlap either the - type or offset fields of swp_entry_t. For x86, offset is at [31:8] and type - at [6:1], with _PAGE_PRESENT at bit 0 for both pte_t and swp_entry_t. This - scheme doesn't map to SH-5 because bit [0] controls cacheability. So bit - [2] is used for _PAGE_PRESENT and the type field of swp_entry_t is split - into 2 pieces. That is handled by SWP_ENTRY and SWP_TYPE below. */ -#define _PAGE_WT 0x001 /* CB0: if cacheable, 1->write-thru, 0->write-back */ -#define _PAGE_DEVICE 0x001 /* CB0: if uncacheable, 1->device (i.e. no write-combining or reordering at bus level) */ -#define _PAGE_CACHABLE 0x002 /* CB1: uncachable/cachable */ -#define _PAGE_PRESENT 0x004 /* software: page referenced */ -#define _PAGE_FILE 0x004 /* software: only when !present */ -#define _PAGE_SIZE0 0x008 /* SZ0-bit : size of page */ -#define _PAGE_SIZE1 0x010 /* SZ1-bit : size of page */ -#define _PAGE_SHARED 0x020 /* software: reflects PTEH's SH */ -#define _PAGE_READ 0x040 /* PR0-bit : read access allowed */ -#define _PAGE_EXECUTE 0x080 /* PR1-bit : execute access allowed */ -#define _PAGE_WRITE 0x100 /* PR2-bit : write access allowed */ -#define _PAGE_USER 0x200 /* PR3-bit : user space access allowed */ -#define _PAGE_DIRTY 0x400 /* software: page accessed in write */ -#define _PAGE_ACCESSED 0x800 /* software: page referenced */ - -/* Mask which drops software flags */ -#define _PAGE_FLAGS_HARDWARE_MASK 0xfffffffffffff3dbLL - -/* - * HugeTLB support - */ -#if defined(CONFIG_HUGETLB_PAGE_SIZE_64K) -#define _PAGE_SZHUGE (_PAGE_SIZE0) -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB) -#define _PAGE_SZHUGE (_PAGE_SIZE1) -#elif defined(CONFIG_HUGETLB_PAGE_SIZE_512MB) -#define _PAGE_SZHUGE (_PAGE_SIZE0 | _PAGE_SIZE1) -#endif - -/* - * Default flags for a Kernel page. - * This is fundametally also SHARED because the main use of this define - * (other than for PGD/PMD entries) is for the VMALLOC pool which is - * contextless. - * - * _PAGE_EXECUTE is required for modules - * - */ -#define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _PAGE_EXECUTE | \ - _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_DIRTY | \ - _PAGE_SHARED) - -/* Default flags for a User page */ -#define _PAGE_TABLE (_KERNPG_TABLE | _PAGE_USER) - -#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) - -#define PAGE_NONE __pgprot(_PAGE_CACHABLE | _PAGE_ACCESSED) -#define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ - _PAGE_CACHABLE | _PAGE_ACCESSED | _PAGE_USER | \ - _PAGE_SHARED) -/* We need to include PAGE_EXECUTE in PAGE_COPY because it is the default - * protection mode for the stack. */ -#define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_USER | _PAGE_EXECUTE) -#define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_CACHABLE | \ - _PAGE_ACCESSED | _PAGE_USER) -#define PAGE_KERNEL __pgprot(_KERNPG_TABLE) - - -/* - * In ST50 we have full permissions (Read/Write/Execute/Shared). - * Just match'em all. These are for mmap(), therefore all at least - * User/Cachable/Present/Accessed. No point in making Fault on Write. - */ -#define __MMAP_COMMON (_PAGE_PRESENT | _PAGE_USER | _PAGE_CACHABLE | _PAGE_ACCESSED) - /* sxwr */ -#define __P000 __pgprot(__MMAP_COMMON) -#define __P001 __pgprot(__MMAP_COMMON | _PAGE_READ) -#define __P010 __pgprot(__MMAP_COMMON) -#define __P011 __pgprot(__MMAP_COMMON | _PAGE_READ) -#define __P100 __pgprot(__MMAP_COMMON | _PAGE_EXECUTE) -#define __P101 __pgprot(__MMAP_COMMON | _PAGE_EXECUTE | _PAGE_READ) -#define __P110 __pgprot(__MMAP_COMMON | _PAGE_EXECUTE) -#define __P111 __pgprot(__MMAP_COMMON | _PAGE_EXECUTE | _PAGE_READ) - -#define __S000 __pgprot(__MMAP_COMMON | _PAGE_SHARED) -#define __S001 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_READ) -#define __S010 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_WRITE) -#define __S011 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_READ | _PAGE_WRITE) -#define __S100 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_EXECUTE) -#define __S101 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_EXECUTE | _PAGE_READ) -#define __S110 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_EXECUTE | _PAGE_WRITE) -#define __S111 __pgprot(__MMAP_COMMON | _PAGE_SHARED | _PAGE_EXECUTE | _PAGE_READ | _PAGE_WRITE) - -/* Make it a device mapping for maximum safety (e.g. for mapping device - registers into user-space via /dev/map). */ -#define pgprot_noncached(x) __pgprot(((x).pgprot & ~(_PAGE_CACHABLE)) | _PAGE_DEVICE) -#define pgprot_writecombine(prot) __pgprot(pgprot_val(prot) & ~_PAGE_CACHABLE) - -/* - * Handling allocation failures during page table setup. - */ -extern void __handle_bad_pmd_kernel(pmd_t * pmd); -#define __handle_bad_pmd(x) __handle_bad_pmd_kernel(x) - -/* - * PTE level access routines. - * - * Note1: - * It's the tree walk leaf. This is physical address to be stored. - * - * Note 2: - * Regarding the choice of _PTE_EMPTY: - - We must choose a bit pattern that cannot be valid, whether or not the page - is present. bit[2]==1 => present, bit[2]==0 => swapped out. If swapped - out, bits [31:8], [6:3], [1:0] are under swapper control, so only bit[7] is - left for us to select. If we force bit[7]==0 when swapped out, we could use - the combination bit[7,2]=2'b10 to indicate an empty PTE. Alternatively, if - we force bit[7]==1 when swapped out, we can use all zeroes to indicate - empty. This is convenient, because the page tables get cleared to zero - when they are allocated. - - */ -#define _PTE_EMPTY 0x0 -#define pte_present(x) (pte_val(x) & _PAGE_PRESENT) -#define pte_clear(mm,addr,xp) (set_pte_at(mm, addr, xp, __pte(_PTE_EMPTY))) -#define pte_none(x) (pte_val(x) == _PTE_EMPTY) - -/* - * Some definitions to translate between mem_map, PTEs, and page - * addresses: - */ - -/* - * Given a PTE, return the index of the mem_map[] entry corresponding - * to the page frame the PTE. Get the absolute physical address, make - * a relative physical address and translate it to an index. - */ -#define pte_pagenr(x) (((unsigned long) (pte_val(x)) - \ - __MEMORY_START) >> PAGE_SHIFT) - -/* - * Given a PTE, return the "struct page *". - */ -#define pte_page(x) (mem_map + pte_pagenr(x)) - -/* - * Return number of (down rounded) MB corresponding to x pages. - */ -#define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT)) - - -/* - * The following have defined behavior only work if pte_present() is true. - */ -static inline int pte_dirty(pte_t pte){ return pte_val(pte) & _PAGE_DIRTY; } -static inline int pte_young(pte_t pte){ return pte_val(pte) & _PAGE_ACCESSED; } -static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } -static inline int pte_write(pte_t pte){ return pte_val(pte) & _PAGE_WRITE; } - -static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_WRITE)); return pte; } -static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; } -static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_WRITE)); return pte; } -static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; } -static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; } -static inline pte_t pte_mkhuge(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_SZHUGE)); return pte; } - - -/* - * Conversion functions: convert a page and protection to a page entry. - * - * extern pte_t mk_pte(struct page *page, pgprot_t pgprot) - */ -#define mk_pte(page,pgprot) \ -({ \ - pte_t __pte; \ - \ - set_pte(&__pte, __pte((((page)-mem_map) << PAGE_SHIFT) | \ - __MEMORY_START | pgprot_val((pgprot)))); \ - __pte; \ -}) - -/* - * This takes a (absolute) physical page address that is used - * by the remapping functions - */ -#define mk_pte_phys(physpage, pgprot) \ -({ pte_t __pte; set_pte(&__pte, __pte(physpage | pgprot_val(pgprot))); __pte; }) - -static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) -{ set_pte(&pte, __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot))); return pte; } - -typedef pte_t *pte_addr_t; -#define pgtable_cache_init() do { } while (0) - -extern void update_mmu_cache(struct vm_area_struct * vma, - unsigned long address, pte_t pte); - -/* Encode and decode a swap entry */ -#define __swp_type(x) (((x).val & 3) + (((x).val >> 1) & 0x3c)) -#define __swp_offset(x) ((x).val >> 8) -#define __swp_entry(type, offset) ((swp_entry_t) { ((offset << 8) + ((type & 0x3c) << 1) + (type & 3)) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) - -/* Encode and decode a nonlinear file mapping entry */ -#define PTE_FILE_MAX_BITS 29 -#define pte_to_pgoff(pte) (pte_val(pte)) -#define pgoff_to_pte(off) ((pte_t) { (off) | _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 io_remap_pfn_range(vma, vaddr, pfn, size, prot) \ - remap_pfn_range(vma, vaddr, pfn, size, prot) - -#endif /* !__ASSEMBLY__ */ - -/* - * No page table caches to initialise - */ -#define pgtable_cache_init() do { } while (0) - -#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)) - -extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; - -#include - -#endif /* __ASM_SH64_PGTABLE_H */ diff -puN include/asm-sh64/platform.h~git-sh /dev/null --- a/include/asm-sh64/platform.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef __ASM_SH64_PLATFORM_H -#define __ASM_SH64_PLATFORM_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/platform.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * benedict.gaster@superh.com: 3rd May 2002 - * Added support for ramdisk, removing statically linked romfs at the same time. - */ - -#include -#include - - -/* - * Platform definition structure. - */ -struct sh64_platform { - unsigned int readonly_rootfs; - unsigned int ramdisk_flags; - unsigned int initial_root_dev; - unsigned int loader_type; - unsigned int initrd_start; - unsigned int initrd_size; - unsigned int fpu_flags; - unsigned int io_res_count; - unsigned int kram_res_count; - unsigned int xram_res_count; - unsigned int rom_res_count; - struct resource *io_res_p; - struct resource *kram_res_p; - struct resource *xram_res_p; - struct resource *rom_res_p; -}; - -extern struct sh64_platform platform_parms; - -extern unsigned long long memory_start, memory_end; - -extern unsigned long long fpu_in_use; - -extern int platform_int_priority[NR_INTC_IRQS]; - -#define FPU_FLAGS (platform_parms.fpu_flags) -#define STANDARD_IO_RESOURCES (platform_parms.io_res_count) -#define STANDARD_KRAM_RESOURCES (platform_parms.kram_res_count) -#define STANDARD_XRAM_RESOURCES (platform_parms.xram_res_count) -#define STANDARD_ROM_RESOURCES (platform_parms.rom_res_count) - -/* - * Kernel Memory description, Respectively: - * code = last but one memory descriptor - * data = last memory descriptor - */ -#define code_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 2]) -#define data_resource (platform_parms.kram_res_p[STANDARD_KRAM_RESOURCES - 1]) - -#endif /* __ASM_SH64_PLATFORM_H */ diff -puN include/asm-sh64/poll.h~git-sh /dev/null --- a/include/asm-sh64/poll.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef __ASM_SH64_POLL_H -#define __ASM_SH64_POLL_H - -#include - -#undef POLLREMOVE - -#endif /* __ASM_SH64_POLL_H */ diff -puN include/asm-sh64/posix_types.h~git-sh /dev/null --- a/include/asm-sh64/posix_types.h +++ /dev/null @@ -1,131 +0,0 @@ -#ifndef __ASM_SH64_POSIX_TYPES_H -#define __ASM_SH64_POSIX_TYPES_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/posix_types.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * 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 long __kernel_ino_t; -typedef unsigned short __kernel_mode_t; -typedef unsigned short __kernel_nlink_t; -typedef long __kernel_off_t; -typedef int __kernel_pid_t; -typedef unsigned short __kernel_ipc_pid_t; -typedef unsigned short __kernel_uid_t; -typedef unsigned short __kernel_gid_t; -typedef long unsigned int __kernel_size_t; -typedef int __kernel_ssize_t; -typedef int __kernel_ptrdiff_t; -typedef long __kernel_time_t; -typedef long __kernel_suseconds_t; -typedef long __kernel_clock_t; -typedef int __kernel_timer_t; -typedef int __kernel_clockid_t; -typedef int __kernel_daddr_t; -typedef char * __kernel_caddr_t; -typedef unsigned short __kernel_uid16_t; -typedef unsigned short __kernel_gid16_t; -typedef unsigned int __kernel_uid32_t; -typedef unsigned int __kernel_gid32_t; - -typedef unsigned short __kernel_old_uid_t; -typedef unsigned short __kernel_old_gid_t; -typedef unsigned short __kernel_old_dev_t; - -#ifdef __GNUC__ -typedef long long __kernel_loff_t; -#endif - -typedef struct { -#if defined(__KERNEL__) || defined(__USE_ALL) - int val[2]; -#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ - int __val[2]; -#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ -} __kernel_fsid_t; - -#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) - -#undef __FD_SET -static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp) -{ - unsigned long __tmp = __fd / __NFDBITS; - unsigned long __rem = __fd % __NFDBITS; - __fdsetp->fds_bits[__tmp] |= (1UL<<__rem); -} - -#undef __FD_CLR -static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp) -{ - unsigned long __tmp = __fd / __NFDBITS; - unsigned long __rem = __fd % __NFDBITS; - __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem); -} - - -#undef __FD_ISSET -static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p) -{ - unsigned long __tmp = __fd / __NFDBITS; - unsigned long __rem = __fd % __NFDBITS; - return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0; -} - -/* - * This will unroll the loop for the normal constant case (8 ints, - * for a 256-bit fd_set) - */ -#undef __FD_ZERO -static __inline__ void __FD_ZERO(__kernel_fd_set *__p) -{ - unsigned long *__tmp = __p->fds_bits; - int __i; - - if (__builtin_constant_p(__FDSET_LONGS)) { - switch (__FDSET_LONGS) { - case 16: - __tmp[ 0] = 0; __tmp[ 1] = 0; - __tmp[ 2] = 0; __tmp[ 3] = 0; - __tmp[ 4] = 0; __tmp[ 5] = 0; - __tmp[ 6] = 0; __tmp[ 7] = 0; - __tmp[ 8] = 0; __tmp[ 9] = 0; - __tmp[10] = 0; __tmp[11] = 0; - __tmp[12] = 0; __tmp[13] = 0; - __tmp[14] = 0; __tmp[15] = 0; - return; - - case 8: - __tmp[ 0] = 0; __tmp[ 1] = 0; - __tmp[ 2] = 0; __tmp[ 3] = 0; - __tmp[ 4] = 0; __tmp[ 5] = 0; - __tmp[ 6] = 0; __tmp[ 7] = 0; - return; - - case 4: - __tmp[ 0] = 0; __tmp[ 1] = 0; - __tmp[ 2] = 0; __tmp[ 3] = 0; - return; - } - } - __i = __FDSET_LONGS; - while (__i) { - __i--; - *__tmp = 0; - __tmp++; - } -} - -#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ - -#endif /* __ASM_SH64_POSIX_TYPES_H */ diff -puN include/asm-sh64/processor.h~git-sh /dev/null --- a/include/asm-sh64/processor.h +++ /dev/null @@ -1,287 +0,0 @@ -#ifndef __ASM_SH64_PROCESSOR_H -#define __ASM_SH64_PROCESSOR_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/processor.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - */ - -#include - -#ifndef __ASSEMBLY__ - -#include -#include -#include -#include -#include - -/* - * Default implementation of macro that returns current - * instruction pointer ("program counter"). - */ -#define current_text_addr() ({ \ -void *pc; \ -unsigned long long __dummy = 0; \ -__asm__("gettr tr0, %1\n\t" \ - "pta 4, tr0\n\t" \ - "gettr tr0, %0\n\t" \ - "ptabs %1, tr0\n\t" \ - :"=r" (pc), "=r" (__dummy) \ - : "1" (__dummy)); \ -pc; }) - -/* - * CPU type and hardware bug flags. Kept separately for each CPU. - */ -enum cpu_type { - CPU_SH5_101, - CPU_SH5_103, - CPU_SH_NONE -}; - -/* - * TLB information structure - * - * Defined for both I and D tlb, per-processor. - */ -struct tlb_info { - unsigned long long next; - unsigned long long first; - unsigned long long last; - - unsigned int entries; - unsigned int step; - - unsigned long flags; -}; - -struct sh_cpuinfo { - enum cpu_type type; - unsigned long loops_per_jiffy; - - char hard_math; - - unsigned long *pgd_quick; - unsigned long *pmd_quick; - unsigned long *pte_quick; - unsigned long pgtable_cache_sz; - unsigned int cpu_clock, master_clock, bus_clock, module_clock; - - /* Cache info */ - struct cache_info icache; - struct cache_info dcache; - - /* TLB info */ - struct tlb_info itlb; - struct tlb_info dtlb; -}; - -extern struct sh_cpuinfo boot_cpu_data; - -#define cpu_data (&boot_cpu_data) -#define current_cpu_data boot_cpu_data - -#endif - -/* - * User space process size: 2GB - 4k. - */ -#define TASK_SIZE 0x7ffff000UL - -/* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -#define TASK_UNMAPPED_BASE (TASK_SIZE / 3) - -/* - * Bit of SR register - * - * FD-bit: - * When it's set, it means the processor doesn't have right to use FPU, - * and it results exception when the floating operation is executed. - * - * IMASK-bit: - * Interrupt level mask - * - * STEP-bit: - * Single step bit - * - */ -#define SR_FD 0x00008000 - -#if defined(CONFIG_SH64_SR_WATCH) -#define SR_MMU 0x84000000 -#else -#define SR_MMU 0x80000000 -#endif - -#define SR_IMASK 0x000000f0 -#define SR_SSTEP 0x08000000 - -#ifndef __ASSEMBLY__ - -/* - * FPU structure and data : require 8-byte alignment as we need to access it - with fld.p, fst.p - */ - -struct sh_fpu_hard_struct { - unsigned long fp_regs[64]; - unsigned int fpscr; - /* long status; * software status information */ -}; - -#if 0 -/* Dummy fpu emulator */ -struct sh_fpu_soft_struct { - unsigned long long fp_regs[32]; - unsigned int fpscr; - unsigned char lookahead; - unsigned long entry_pc; -}; -#endif - -union sh_fpu_union { - struct sh_fpu_hard_struct hard; - /* 'hard' itself only produces 32 bit alignment, yet we need - to access it using 64 bit load/store as well. */ - unsigned long long alignment_dummy; -}; - -struct thread_struct { - unsigned long sp; - unsigned long pc; - /* This stores the address of the pt_regs built during a context - switch, or of the register save area built for a kernel mode - exception. It is used for backtracing the stack of a sleeping task - or one that traps in kernel mode. */ - struct pt_regs *kregs; - /* This stores the address of the pt_regs constructed on entry from - user mode. It is a fixed value over the lifetime of a process, or - NULL for a kernel thread. */ - struct pt_regs *uregs; - - unsigned long trap_no, error_code; - unsigned long address; - /* Hardware debugging registers may come here */ - - /* floating point info */ - union sh_fpu_union fpu; -}; - -#define INIT_MMAP \ -{ &init_mm, 0, 0, NULL, PAGE_SHARED, VM_READ | VM_WRITE | VM_EXEC, 1, NULL, NULL } - -extern struct pt_regs fake_swapper_regs; - -#define INIT_THREAD { \ - .sp = sizeof(init_stack) + \ - (long) &init_stack, \ - .pc = 0, \ - .kregs = &fake_swapper_regs, \ - .uregs = NULL, \ - .trap_no = 0, \ - .error_code = 0, \ - .address = 0, \ - .fpu = { { { 0, } }, } \ -} - -/* - * Do necessary setup to start up a newly executed thread. - */ -#define SR_USER (SR_MMU | SR_FD) - -#define start_thread(regs, new_pc, new_sp) \ - set_fs(USER_DS); \ - regs->sr = SR_USER; /* User mode. */ \ - regs->pc = new_pc - 4; /* Compensate syscall exit */ \ - regs->pc |= 1; /* Set SHmedia ! */ \ - regs->regs[18] = 0; \ - regs->regs[15] = new_sp - -/* Forward declaration, a strange C thing */ -struct task_struct; -struct mm_struct; - -/* Free all resources held by a thread. */ -extern void release_thread(struct task_struct *); -/* - * create a kernel thread without removing it from tasklists - */ -extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); - - -/* Copy and release all segment info associated with a VM */ -#define copy_segments(p, mm) do { } while (0) -#define release_segments(mm) do { } while (0) -#define forget_segments() do { } while (0) -#define prepare_to_copy(tsk) do { } while (0) -/* - * FPU lazy state save handling. - */ - -static inline void release_fpu(void) -{ - unsigned long long __dummy; - - /* Set FD flag in SR */ - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "or %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy) - : "r" (SR_FD)); -} - -static inline void grab_fpu(void) -{ - unsigned long long __dummy; - - /* Clear out FD flag in SR */ - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy) - : "r" (~SR_FD)); -} - -/* Round to nearest, no exceptions on inexact, overflow, underflow, - zero-divide, invalid. Configure option for whether to flush denorms to - zero, or except if a denorm is encountered. */ -#if defined(CONFIG_SH64_FPU_DENORM_FLUSH) -#define FPSCR_INIT 0x00040000 -#else -#define FPSCR_INIT 0x00000000 -#endif - -/* Save the current FP regs */ -void fpsave(struct sh_fpu_hard_struct *fpregs); - -/* Initialise the FP state of a task */ -void fpinit(struct sh_fpu_hard_struct *fpregs); - -extern struct task_struct *last_task_used_math; - -/* - * Return saved PC of a blocked thread. - */ -#define thread_saved_pc(tsk) (tsk->thread.pc) - -extern unsigned long get_wchan(struct task_struct *p); - -#define KSTK_EIP(tsk) ((tsk)->thread.pc) -#define KSTK_ESP(tsk) ((tsk)->thread.sp) - -#define cpu_relax() barrier() - -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_SH64_PROCESSOR_H */ - diff -puN include/asm-sh64/ptrace.h~git-sh /dev/null --- a/include/asm-sh64/ptrace.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __ASM_SH64_PTRACE_H -#define __ASM_SH64_PTRACE_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/ptrace.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * This struct defines the way the registers are stored on the - * kernel stack during a system call or other kernel entry. - */ -struct pt_regs { - unsigned long long pc; - unsigned long long sr; - unsigned long long syscall_nr; - unsigned long long regs[63]; - unsigned long long tregs[8]; - unsigned long long pad[2]; -}; - -#ifdef __KERNEL__ -#define user_mode(regs) (((regs)->sr & 0x40000000)==0) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) ((unsigned long)instruction_pointer(regs)) -extern void show_regs(struct pt_regs *); -#endif - -#endif /* __ASM_SH64_PTRACE_H */ diff -puN include/asm-sh64/registers.h~git-sh /dev/null --- a/include/asm-sh64/registers.h +++ /dev/null @@ -1,106 +0,0 @@ -#ifndef __ASM_SH64_REGISTERS_H -#define __ASM_SH64_REGISTERS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/registers.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2004 Richard Curnow - */ - -#ifdef __ASSEMBLY__ -/* ===================================================================== -** -** Section 1: acts on assembly sources pre-processed by GPP ( ). -** Assigns symbolic names to control & target registers. -*/ - -/* - * Define some useful aliases for control registers. - */ -#define SR cr0 -#define SSR cr1 -#define PSSR cr2 - /* cr3 UNDEFINED */ -#define INTEVT cr4 -#define EXPEVT cr5 -#define PEXPEVT cr6 -#define TRA cr7 -#define SPC cr8 -#define PSPC cr9 -#define RESVEC cr10 -#define VBR cr11 - /* cr12 UNDEFINED */ -#define TEA cr13 - /* cr14-cr15 UNDEFINED */ -#define DCR cr16 -#define KCR0 cr17 -#define KCR1 cr18 - /* cr19-cr31 UNDEFINED */ - /* cr32-cr61 RESERVED */ -#define CTC cr62 -#define USR cr63 - -/* - * ABI dependent registers (general purpose set) - */ -#define RET r2 -#define ARG1 r2 -#define ARG2 r3 -#define ARG3 r4 -#define ARG4 r5 -#define ARG5 r6 -#define ARG6 r7 -#define SP r15 -#define LINK r18 -#define ZERO r63 - -/* - * Status register defines: used only by assembly sources (and - * syntax independednt) - */ -#define SR_RESET_VAL 0x0000000050008000 -#define SR_HARMLESS 0x00000000500080f0 /* Write ignores for most */ -#define SR_ENABLE_FPU 0xffffffffffff7fff /* AND with this */ - -#if defined (CONFIG_SH64_SR_WATCH) -#define SR_ENABLE_MMU 0x0000000084000000 /* OR with this */ -#else -#define SR_ENABLE_MMU 0x0000000080000000 /* OR with this */ -#endif - -#define SR_UNBLOCK_EXC 0xffffffffefffffff /* AND with this */ -#define SR_BLOCK_EXC 0x0000000010000000 /* OR with this */ - -#else /* Not __ASSEMBLY__ syntax */ - -/* -** Stringify reg. name -*/ -#define __str(x) #x - -/* Stringify control register names for use in inline assembly */ -#define __SR __str(SR) -#define __SSR __str(SSR) -#define __PSSR __str(PSSR) -#define __INTEVT __str(INTEVT) -#define __EXPEVT __str(EXPEVT) -#define __PEXPEVT __str(PEXPEVT) -#define __TRA __str(TRA) -#define __SPC __str(SPC) -#define __PSPC __str(PSPC) -#define __RESVEC __str(RESVEC) -#define __VBR __str(VBR) -#define __TEA __str(TEA) -#define __DCR __str(DCR) -#define __KCR0 __str(KCR0) -#define __KCR1 __str(KCR1) -#define __CTC __str(CTC) -#define __USR __str(USR) - -#endif /* __ASSEMBLY__ */ -#endif /* __ASM_SH64_REGISTERS_H */ diff -puN include/asm-sh64/resource.h~git-sh /dev/null --- a/include/asm-sh64/resource.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_RESOURCE_H -#define __ASM_SH64_RESOURCE_H - -#include - -#endif /* __ASM_SH64_RESOURCE_H */ diff -puN include/asm-sh64/scatterlist.h~git-sh /dev/null --- a/include/asm-sh64/scatterlist.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/scatterlist.h - * - * Copyright (C) 2003 Paul Mundt - * - */ -#ifndef __ASM_SH64_SCATTERLIST_H -#define __ASM_SH64_SCATTERLIST_H - -#include - -struct scatterlist { -#ifdef CONFIG_DEBUG_SG - unsigned long sg_magic; -#endif - unsigned long page_link; - unsigned int offset;/* for highmem, page offset */ - dma_addr_t dma_address; - unsigned int length; -}; - -/* These macros should be used after a pci_map_sg call has been done - * to get bus addresses of each of the SG entries and their lengths. - * You should only work with the number of sg entries pci_map_sg - * returns, or alternatively stop on the first sg_dma_len(sg) which - * is 0. - */ -#define sg_dma_address(sg) ((sg)->dma_address) -#define sg_dma_len(sg) ((sg)->length) - -#define ISA_DMA_THRESHOLD (0xffffffff) - -#endif /* !__ASM_SH64_SCATTERLIST_H */ diff -puN include/asm-sh64/sci.h~git-sh /dev/null --- a/include/asm-sh64/sci.h +++ /dev/null @@ -1 +0,0 @@ -#include diff -puN include/asm-sh64/sections.h~git-sh /dev/null --- a/include/asm-sh64/sections.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __ASM_SH64_SECTIONS_H -#define __ASM_SH64_SECTIONS_H - -#include - -#endif /* __ASM_SH64_SECTIONS_H */ - diff -puN include/asm-sh64/segment.h~git-sh /dev/null --- a/include/asm-sh64/segment.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_SEGMENT_H -#define _ASM_SEGMENT_H - -/* Only here because we have some old header files that expect it.. */ - -#endif /* _ASM_SEGMENT_H */ diff -puN include/asm-sh64/semaphore-helper.h~git-sh /dev/null --- a/include/asm-sh64/semaphore-helper.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef __ASM_SH64_SEMAPHORE_HELPER_H -#define __ASM_SH64_SEMAPHORE_HELPER_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/semaphore-helper.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ -#include - -/* - * SMP- and interrupt-safe semaphores helper functions. - * - * (C) Copyright 1996 Linus Torvalds - * (C) Copyright 1999 Andrea Arcangeli - */ - -/* - * These two _must_ execute atomically wrt each other. - * - * This is trivially done with load_locked/store_cond, - * which we have. Let the rest of the losers suck eggs. - */ -static __inline__ void wake_one_more(struct semaphore * sem) -{ - atomic_inc((atomic_t *)&sem->sleepers); -} - -static __inline__ int waking_non_zero(struct semaphore *sem) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&semaphore_wake_lock, flags); - if (sem->sleepers > 0) { - sem->sleepers--; - ret = 1; - } - spin_unlock_irqrestore(&semaphore_wake_lock, flags); - return ret; -} - -/* - * waking_non_zero_interruptible: - * 1 got the lock - * 0 go to sleep - * -EINTR interrupted - * - * We must undo the sem->count down_interruptible() increment while we are - * protected by the spinlock in order to make atomic this atomic_inc() with the - * atomic_read() in wake_one_more(), otherwise we can race. -arca - */ -static __inline__ int waking_non_zero_interruptible(struct semaphore *sem, - struct task_struct *tsk) -{ - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&semaphore_wake_lock, flags); - if (sem->sleepers > 0) { - sem->sleepers--; - ret = 1; - } else if (signal_pending(tsk)) { - atomic_inc(&sem->count); - ret = -EINTR; - } - spin_unlock_irqrestore(&semaphore_wake_lock, flags); - return ret; -} - -/* - * waking_non_zero_trylock: - * 1 failed to lock - * 0 got the lock - * - * We must undo the sem->count down_trylock() increment while we are - * protected by the spinlock in order to make atomic this atomic_inc() with the - * atomic_read() in wake_one_more(), otherwise we can race. -arca - */ -static __inline__ int waking_non_zero_trylock(struct semaphore *sem) -{ - unsigned long flags; - int ret = 1; - - spin_lock_irqsave(&semaphore_wake_lock, flags); - if (sem->sleepers <= 0) - atomic_inc(&sem->count); - else { - sem->sleepers--; - ret = 0; - } - spin_unlock_irqrestore(&semaphore_wake_lock, flags); - return ret; -} - -#endif /* __ASM_SH64_SEMAPHORE_HELPER_H */ diff -puN include/asm-sh64/semaphore.h~git-sh /dev/null --- a/include/asm-sh64/semaphore.h +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef __ASM_SH64_SEMAPHORE_H -#define __ASM_SH64_SEMAPHORE_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/semaphore.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * SMP- and interrupt-safe semaphores. - * - * (C) Copyright 1996 Linus Torvalds - * - * SuperH verison by Niibe Yutaka - * (Currently no asm implementation but generic C code...) - * - */ - -#include -#include -#include -#include - -#include -#include - -struct semaphore { - atomic_t count; - int sleepers; - wait_queue_head_t wait; -}; - -#define __SEMAPHORE_INITIALIZER(name, n) \ -{ \ - .count = ATOMIC_INIT(n), \ - .sleepers = 0, \ - .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \ -} - -#define __DECLARE_SEMAPHORE_GENERIC(name,count) \ - struct semaphore name = __SEMAPHORE_INITIALIZER(name,count) - -#define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1) - -static inline void sema_init (struct semaphore *sem, int val) -{ -/* - * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val); - * - * i'd rather use the more flexible initialization above, but sadly - * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well. - */ - atomic_set(&sem->count, val); - sem->sleepers = 0; - init_waitqueue_head(&sem->wait); -} - -static inline void init_MUTEX (struct semaphore *sem) -{ - sema_init(sem, 1); -} - -static inline void init_MUTEX_LOCKED (struct semaphore *sem) -{ - sema_init(sem, 0); -} - -#if 0 -asmlinkage void __down_failed(void /* special register calling convention */); -asmlinkage int __down_failed_interruptible(void /* params in registers */); -asmlinkage int __down_failed_trylock(void /* params in registers */); -asmlinkage void __up_wakeup(void /* special register calling convention */); -#endif - -asmlinkage void __down(struct semaphore * sem); -asmlinkage int __down_interruptible(struct semaphore * sem); -asmlinkage int __down_trylock(struct semaphore * sem); -asmlinkage void __up(struct semaphore * sem); - -extern spinlock_t semaphore_wake_lock; - -static inline void down(struct semaphore * sem) -{ - if (atomic_dec_return(&sem->count) < 0) - __down(sem); -} - -static inline int down_interruptible(struct semaphore * sem) -{ - int ret = 0; - - if (atomic_dec_return(&sem->count) < 0) - ret = __down_interruptible(sem); - return ret; -} - -static inline int down_trylock(struct semaphore * sem) -{ - int ret = 0; - - if (atomic_dec_return(&sem->count) < 0) - ret = __down_trylock(sem); - return ret; -} - -/* - * Note! This is subtle. We jump to wake people up only if - * the semaphore was negative (== somebody was waiting on it). - */ -static inline void up(struct semaphore * sem) -{ - if (atomic_inc_return(&sem->count) <= 0) - __up(sem); -} - -#endif /* __ASM_SH64_SEMAPHORE_H */ diff -puN include/asm-sh64/sembuf.h~git-sh /dev/null --- a/include/asm-sh64/sembuf.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __ASM_SH64_SEMBUF_H -#define __ASM_SH64_SEMBUF_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/sembuf.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * The semid64_ds structure for i386 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_SH64_SEMBUF_H */ diff -puN include/asm-sh64/serial.h~git-sh /dev/null --- a/include/asm-sh64/serial.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * include/asm-sh64/serial.h - * - * Configuration details for 8250, 16450, 16550, etc. serial ports - */ - -#ifndef _ASM_SERIAL_H -#define _ASM_SERIAL_H - -/* - * This assumes you have a 1.8432 MHz clock for your UART. - * - * It'd be nice if someone built a serial card with a 24.576 MHz - * clock, since the 16550A is capable of handling a top speed of 1.5 - * megabits/second; but this requires the faster clock. - */ -#define BASE_BAUD ( 1843200 / 16 ) - -#define RS_TABLE_SIZE 2 - -#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST) - -#define SERIAL_PORT_DFNS \ - /* UART CLK PORT IRQ FLAGS */ \ - { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS }, /* ttyS0 */ \ - { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS } /* ttyS1 */ - -/* XXX: This should be moved ino irq.h */ -#define irq_cannonicalize(x) (x) - -#endif /* _ASM_SERIAL_H */ diff -puN include/asm-sh64/setup.h~git-sh /dev/null --- a/include/asm-sh64/setup.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __ASM_SH64_SETUP_H -#define __ASM_SH64_SETUP_H - -#define COMMAND_LINE_SIZE 256 - -#ifdef __KERNEL__ - -#define PARAM ((unsigned char *)empty_zero_page) -#define MOUNT_ROOT_RDONLY (*(unsigned long *) (PARAM+0x000)) -#define RAMDISK_FLAGS (*(unsigned long *) (PARAM+0x004)) -#define ORIG_ROOT_DEV (*(unsigned long *) (PARAM+0x008)) -#define LOADER_TYPE (*(unsigned long *) (PARAM+0x00c)) -#define INITRD_START (*(unsigned long *) (PARAM+0x010)) -#define INITRD_SIZE (*(unsigned long *) (PARAM+0x014)) - -#define COMMAND_LINE ((char *) (PARAM+256)) -#define COMMAND_LINE_SIZE 256 - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_SETUP_H */ - diff -puN include/asm-sh64/shmbuf.h~git-sh /dev/null --- a/include/asm-sh64/shmbuf.h +++ /dev/null @@ -1,53 +0,0 @@ -#ifndef __ASM_SH64_SHMBUF_H -#define __ASM_SH64_SHMBUF_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/shmbuf.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* - * The shmid64_ds structure for i386 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_SH64_SHMBUF_H */ diff -puN include/asm-sh64/shmparam.h~git-sh /dev/null --- a/include/asm-sh64/shmparam.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __ASM_SH64_SHMPARAM_H -#define __ASM_SH64_SHMPARAM_H - -/* - * Set this to a sensible safe default, we'll work out the specifics for the - * align mask from the cache descriptor at run-time. - */ -#define SHMLBA 0x4000 - -#define __ARCH_FORCE_SHMLBA - -#endif /* __ASM_SH64_SHMPARAM_H */ diff -puN include/asm-sh64/sigcontext.h~git-sh /dev/null --- a/include/asm-sh64/sigcontext.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef __ASM_SH64_SIGCONTEXT_H -#define __ASM_SH64_SIGCONTEXT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/sigcontext.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -struct sigcontext { - unsigned long oldmask; - - /* CPU registers */ - unsigned long long sc_regs[63]; - unsigned long long sc_tregs[8]; - unsigned long long sc_pc; - unsigned long long sc_sr; - - /* FPU registers */ - unsigned long long sc_fpregs[32]; - unsigned int sc_fpscr; - unsigned int sc_fpvalid; -}; - -#endif /* __ASM_SH64_SIGCONTEXT_H */ diff -puN include/asm-sh64/siginfo.h~git-sh /dev/null --- a/include/asm-sh64/siginfo.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_SIGINFO_H -#define __ASM_SH64_SIGINFO_H - -#include - -#endif /* __ASM_SH64_SIGINFO_H */ diff -puN include/asm-sh64/signal.h~git-sh /dev/null --- a/include/asm-sh64/signal.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef __ASM_SH64_SIGNAL_H -#define __ASM_SH64_SIGNAL_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/signal.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX (_NSIG-1) - -/* - * SA_FLAGS values: - * - * SA_ONSTACK indicates that a registered stack_t will be used. - * SA_RESTART flag to get restarting signals (which were the default long ago) - * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. - * SA_RESETHAND clears the handler when the signal is delivered. - * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies. - * SA_NODEFER prevents the current signal from being masked in the handler. - * - * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single - * Unix names RESETHAND and NODEFER respectively. - */ -#define SA_NOCLDSTOP 0x00000001 -#define SA_NOCLDWAIT 0x00000002 /* not supported yet */ -#define SA_SIGINFO 0x00000004 -#define SA_ONSTACK 0x08000000 -#define SA_RESTART 0x10000000 -#define SA_NODEFER 0x40000000 -#define SA_RESETHAND 0x80000000 - -#define SA_NOMASK SA_NODEFER -#define SA_ONESHOT SA_RESETHAND - -#define SA_RESTORER 0x04000000 - -/* - * sigaltstack controls - */ -#define SS_ONSTACK 1 -#define SS_DISABLE 2 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ THREAD_SIZE - -#include - -#ifdef __KERNEL__ -struct old_sigaction { - __sighandler_t sa_handler; - old_sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -struct sigaction { - __sighandler_t sa_handler; - unsigned long sa_flags; - void (*sa_restorer)(void); - sigset_t sa_mask; /* mask last for extensibility */ -}; - -struct k_sigaction { - struct sigaction sa; -}; -#else -/* 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__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - -#ifdef __KERNEL__ -#include - -#define sigmask(sig) (1UL << ((sig) - 1)) -#define ptrace_signal_deliver(regs, cookie) do { } while (0) - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_SIGNAL_H */ diff -puN include/asm-sh64/smp.h~git-sh /dev/null --- a/include/asm-sh64/smp.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ASM_SH64_SMP_H -#define __ASM_SH64_SMP_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/smp.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#endif /* __ASM_SH64_SMP_H */ diff -puN include/asm-sh64/socket.h~git-sh /dev/null --- a/include/asm-sh64/socket.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_SOCKET_H -#define __ASM_SH64_SOCKET_H - -#include - -#endif /* __ASM_SH64_SOCKET_H */ diff -puN include/asm-sh64/sockios.h~git-sh /dev/null --- a/include/asm-sh64/sockios.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __ASM_SH64_SOCKIOS_H -#define __ASM_SH64_SOCKIOS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/sockios.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -/* Socket-level I/O control calls. */ -#define FIOGETOWN _IOR('f', 123, int) -#define FIOSETOWN _IOW('f', 124, int) - -#define SIOCATMARK _IOR('s', 7, int) -#define SIOCSPGRP _IOW('s', 8, pid_t) -#define SIOCGPGRP _IOR('s', 9, pid_t) - -#define SIOCGSTAMP _IOR('s', 100, struct timeval) /* Get stamp (timeval) */ -#define SIOCGSTAMPNS _IOR('s', 101, struct timespec) /* Get stamp (timespec) */ -#endif /* __ASM_SH64_SOCKIOS_H */ diff -puN include/asm-sh64/spinlock.h~git-sh /dev/null --- a/include/asm-sh64/spinlock.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __ASM_SH64_SPINLOCK_H -#define __ASM_SH64_SPINLOCK_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/spinlock.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#error "No SMP on SH64" - -#endif /* __ASM_SH64_SPINLOCK_H */ diff -puN include/asm-sh64/stat.h~git-sh /dev/null --- a/include/asm-sh64/stat.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __ASM_SH64_STAT_H -#define __ASM_SH64_STAT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/stat.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -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; -}; - -struct stat { - unsigned short st_dev; - unsigned short __pad1; - unsigned long st_ino; - unsigned short st_mode; - unsigned short st_nlink; - unsigned short st_uid; - unsigned short st_gid; - unsigned short st_rdev; - unsigned short __pad2; - unsigned long st_size; - unsigned long st_blksize; - unsigned long st_blocks; - unsigned long st_atime; - unsigned long st_atime_nsec; - unsigned long st_mtime; - unsigned long st_mtime_nsec; - unsigned long st_ctime; - unsigned long st_ctime_nsec; - unsigned long __unused4; - unsigned long __unused5; -}; - -/* This matches struct stat64 in glibc2.1, hence the absolutely - * insane amounts of padding around dev_t's. - */ -struct stat64 { - unsigned short st_dev; - unsigned char __pad0[10]; - - unsigned long st_ino; - unsigned int st_mode; - unsigned int st_nlink; - - unsigned long st_uid; - unsigned long st_gid; - - unsigned short st_rdev; - unsigned char __pad3[10]; - - long long st_size; - unsigned long st_blksize; - - unsigned long st_blocks; /* Number 512-byte blocks allocated. */ - unsigned long __pad4; /* future possible st_blocks high bits */ - - unsigned long st_atime; - unsigned long st_atime_nsec; - - unsigned long st_mtime; - unsigned long st_mtime_nsec; - - unsigned long st_ctime; - unsigned long st_ctime_nsec; /* will be high 32 bits of ctime someday */ - - unsigned long __unused1; - unsigned long __unused2; -}; - -#endif /* __ASM_SH64_STAT_H */ diff -puN include/asm-sh64/statfs.h~git-sh /dev/null --- a/include/asm-sh64/statfs.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_STATFS_H -#define __ASM_SH64_STATFS_H - -#include - -#endif /* __ASM_SH64_STATFS_H */ diff -puN include/asm-sh64/string.h~git-sh /dev/null --- a/include/asm-sh64/string.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __ASM_SH64_STRING_H -#define __ASM_SH64_STRING_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/string.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - * Empty on purpose. ARCH SH64 ASM libs are out of the current project scope. - * - */ - -#define __HAVE_ARCH_MEMCPY - -extern void *memcpy(void *dest, const void *src, size_t count); - -#endif diff -puN include/asm-sh64/system.h~git-sh /dev/null --- a/include/asm-sh64/system.h +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef __ASM_SH64_SYSTEM_H -#define __ASM_SH64_SYSTEM_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/system.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * Copyright (C) 2004 Richard Curnow - * - */ - -#include -#include - -/* - * switch_to() should switch tasks to task nr n, first - */ - -typedef struct { - unsigned long seg; -} mm_segment_t; - -extern struct task_struct *sh64_switch_to(struct task_struct *prev, - struct thread_struct *prev_thread, - struct task_struct *next, - struct thread_struct *next_thread); - -#define switch_to(prev,next,last) \ - do {\ - if (last_task_used_math != next) {\ - struct pt_regs *regs = next->thread.uregs;\ - if (regs) regs->sr |= SR_FD;\ - }\ - last = sh64_switch_to(prev, &prev->thread, next, &next->thread);\ - } while(0) - -#define nop() __asm__ __volatile__ ("nop") - -#define xchg(ptr,x) ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr)))) - -extern void __xchg_called_with_bad_pointer(void); - -#define mb() __asm__ __volatile__ ("synco": : :"memory") -#define rmb() mb() -#define wmb() __asm__ __volatile__ ("synco": : :"memory") -#define read_barrier_depends() do { } while (0) - -#ifdef CONFIG_SMP -#define smp_mb() mb() -#define smp_rmb() rmb() -#define smp_wmb() wmb() -#define smp_read_barrier_depends() read_barrier_depends() -#else -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() -#define smp_read_barrier_depends() do { } while (0) -#endif /* CONFIG_SMP */ - -#define set_mb(var, value) do { (void)xchg(&var, value); } while (0) - -/* Interrupt Control */ -#ifndef HARD_CLI -#define SR_MASK_L 0x000000f0L -#define SR_MASK_LL 0x00000000000000f0LL -#else -#define SR_MASK_L 0x10000000L -#define SR_MASK_LL 0x0000000010000000LL -#endif - -static __inline__ void local_irq_enable(void) -{ - /* cli/sti based on SR.BL */ - unsigned long long __dummy0, __dummy1=~SR_MASK_LL; - - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "and %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} - -static __inline__ void local_irq_disable(void) -{ - /* cli/sti based on SR.BL */ - unsigned long long __dummy0, __dummy1=SR_MASK_LL; - __asm__ __volatile__("getcon " __SR ", %0\n\t" - "or %0, %1, %0\n\t" - "putcon %0, " __SR "\n\t" - : "=&r" (__dummy0) - : "r" (__dummy1)); -} - -#define local_save_flags(x) \ -(__extension__ ({ unsigned long long __dummy=SR_MASK_LL; \ - __asm__ __volatile__( \ - "getcon " __SR ", %0\n\t" \ - "and %0, %1, %0" \ - : "=&r" (x) \ - : "r" (__dummy));})) - -#define local_irq_save(x) \ -(__extension__ ({ unsigned long long __d2=SR_MASK_LL, __d1; \ - __asm__ __volatile__( \ - "getcon " __SR ", %1\n\t" \ - "or %1, r63, %0\n\t" \ - "or %1, %2, %1\n\t" \ - "putcon %1, " __SR "\n\t" \ - "and %0, %2, %0" \ - : "=&r" (x), "=&r" (__d1) \ - : "r" (__d2));})); - -#define local_irq_restore(x) do { \ - if ( ((x) & SR_MASK_L) == 0 ) /* dropping to 0 ? */ \ - local_irq_enable(); /* yes...re-enable */ \ -} while (0) - -#define irqs_disabled() \ -({ \ - unsigned long flags; \ - local_save_flags(flags); \ - (flags != 0); \ -}) - -static inline unsigned long xchg_u32(volatile int * m, unsigned long val) -{ - unsigned long flags, retval; - - local_irq_save(flags); - retval = *m; - *m = val; - local_irq_restore(flags); - return retval; -} - -static inline unsigned long xchg_u8(volatile unsigned char * m, unsigned long val) -{ - unsigned long flags, retval; - - local_irq_save(flags); - retval = *m; - *m = val & 0xff; - local_irq_restore(flags); - return retval; -} - -static __inline__ unsigned long __xchg(unsigned long x, volatile void * ptr, int size) -{ - switch (size) { - case 4: - return xchg_u32(ptr, x); - break; - case 1: - return xchg_u8(ptr, x); - break; - } - __xchg_called_with_bad_pointer(); - return x; -} - -/* XXX - * disable hlt during certain critical i/o operations - */ -#define HAVE_DISABLE_HLT -void disable_hlt(void); -void enable_hlt(void); - - -#define smp_mb() barrier() -#define smp_rmb() barrier() -#define smp_wmb() barrier() - -#ifdef CONFIG_SH_ALPHANUMERIC -/* This is only used for debugging. */ -extern void print_seg(char *file,int line); -#define PLS() print_seg(__FILE__,__LINE__) -#else /* CONFIG_SH_ALPHANUMERIC */ -#define PLS() -#endif /* CONFIG_SH_ALPHANUMERIC */ - -#define PL() printk("@ <%s,%s:%d>\n",__FILE__,__FUNCTION__,__LINE__) - -#define arch_align_stack(x) (x) - -#endif /* __ASM_SH64_SYSTEM_H */ diff -puN include/asm-sh64/termbits.h~git-sh /dev/null --- a/include/asm-sh64/termbits.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_TERMBITS_H -#define __ASM_SH64_TERMBITS_H - -#include - -#endif /* __ASM_SH64_TERMBITS_H */ diff -puN include/asm-sh64/termios.h~git-sh /dev/null --- a/include/asm-sh64/termios.h +++ /dev/null @@ -1,99 +0,0 @@ -#ifndef __ASM_SH64_TERMIOS_H -#define __ASM_SH64_TERMIOS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/termios.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include -#include - -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 - -/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ - -#ifdef __KERNEL__ - -/* 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" - -/* - * Translate a "termio" structure into a "termios". Ugh. - */ -#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \ - unsigned short __tmp; \ - get_user(__tmp,&(termio)->x); \ - *(unsigned short *) &(termios)->x = __tmp; \ -} - -#define user_termio_to_kernel_termios(termios, termio) \ -({ \ - SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \ - SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \ - copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \ -}) - -/* - * Translate a "termios" structure into a "termio". Ugh. - */ -#define kernel_termios_to_user_termio(termio, termios) \ -({ \ - put_user((termios)->c_iflag, &(termio)->c_iflag); \ - put_user((termios)->c_oflag, &(termio)->c_oflag); \ - put_user((termios)->c_cflag, &(termio)->c_cflag); \ - put_user((termios)->c_lflag, &(termio)->c_lflag); \ - put_user((termios)->c_line, &(termio)->c_line); \ - copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ -}) - -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_TERMIOS_H */ diff -puN include/asm-sh64/thread_info.h~git-sh /dev/null --- a/include/asm-sh64/thread_info.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef __ASM_SH64_THREAD_INFO_H -#define __ASM_SH64_THREAD_INFO_H - -/* - * SuperH 5 version - * Copyright (C) 2003 Paul Mundt - */ - -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ -#include - -/* - * 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 - */ -struct thread_info { - struct task_struct *task; /* main task structure */ - struct exec_domain *exec_domain; /* execution domain */ - unsigned long flags; /* low level flags */ - /* Put the 4 32-bit fields together to make asm offsetting easier. */ - int preempt_count; /* 0 => preemptable, <0 => BUG */ - __u16 cpu; - - mm_segment_t addr_limit; - struct restart_block restart_block; - - __u8 supervisor_stack[0]; -}; - -/* - * macros/functions for gaining access to the thread information structure - */ -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .exec_domain = &default_exec_domain, \ - .flags = 0, \ - .cpu = 0, \ - .preempt_count = 1, \ - .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 */ -static inline struct thread_info *current_thread_info(void) -{ - struct thread_info *ti; - - __asm__ __volatile__ ("getcon " __KCR0 ", %0\n\t" : "=r" (ti)); - - return ti; -} - -/* thread information allocation */ - - - -#define alloc_thread_info(ti) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1)) -#define free_thread_info(ti) free_pages((unsigned long) (ti), 1) - -#endif /* __ASSEMBLY__ */ - -#define THREAD_SIZE 8192 - -#define PREEMPT_ACTIVE 0x10000000 - -/* thread information flags */ -#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_SIGPENDING 2 /* signal pending */ -#define TIF_NEED_RESCHED 3 /* rescheduling necessary */ -#define TIF_MEMDIE 4 -#define TIF_RESTORE_SIGMASK 5 /* Restore signal mask in do_signal */ - -#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_MEMDIE (1 << TIF_MEMDIE) -#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_THREAD_INFO_H */ diff -puN include/asm-sh64/timex.h~git-sh /dev/null --- a/include/asm-sh64/timex.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef __ASM_SH64_TIMEX_H -#define __ASM_SH64_TIMEX_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/timex.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 Paul Mundt - * - * sh-5 architecture timex specifications - * - */ - -#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 /* __ASM_SH64_TIMEX_H */ diff -puN include/asm-sh64/tlb.h~git-sh /dev/null --- a/include/asm-sh64/tlb.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * include/asm-sh64/tlb.h - * - * Copyright (C) 2003 Paul Mundt - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - */ -#ifndef __ASM_SH64_TLB_H -#define __ASM_SH64_TLB_H - -/* - * Note! These are mostly unused, we just need the xTLB_LAST_VAR_UNRESTRICTED - * for head.S! Once this limitation is gone, we can clean the rest of this up. - */ - -/* ITLB defines */ -#define ITLB_FIXED 0x00000000 /* First fixed ITLB, see head.S */ -#define ITLB_LAST_VAR_UNRESTRICTED 0x000003F0 /* Last ITLB */ - -/* DTLB defines */ -#define DTLB_FIXED 0x00800000 /* First fixed DTLB, see head.S */ -#define DTLB_LAST_VAR_UNRESTRICTED 0x008003F0 /* Last DTLB */ - -#ifndef __ASSEMBLY__ - -/** - * for_each_dtlb_entry - * - * @tlb: TLB entry - * - * Iterate over free (non-wired) DTLB entries - */ -#define for_each_dtlb_entry(tlb) \ - for (tlb = cpu_data->dtlb.first; \ - tlb <= cpu_data->dtlb.last; \ - tlb += cpu_data->dtlb.step) - -/** - * for_each_itlb_entry - * - * @tlb: TLB entry - * - * Iterate over free (non-wired) ITLB entries - */ -#define for_each_itlb_entry(tlb) \ - for (tlb = cpu_data->itlb.first; \ - tlb <= cpu_data->itlb.last; \ - tlb += cpu_data->itlb.step) - -/** - * __flush_tlb_slot - * - * @slot: Address of TLB slot. - * - * Flushes TLB slot @slot. - */ -static inline void __flush_tlb_slot(unsigned long long slot) -{ - __asm__ __volatile__ ("putcfg %0, 0, r63\n" : : "r" (slot)); -} - -/* arch/sh64/mm/tlb.c */ -extern int sh64_tlb_init(void); -extern unsigned long long sh64_next_free_dtlb_entry(void); -extern unsigned long long sh64_get_wired_dtlb_entry(void); -extern int sh64_put_wired_dtlb_entry(unsigned long long entry); - -extern void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr, unsigned long asid, unsigned long paddr); -extern void sh64_teardown_tlb_slot(unsigned long long config_addr); - -#define tlb_start_vma(tlb, vma) \ - flush_cache_range(vma, vma->vm_start, vma->vm_end) - -#define tlb_end_vma(tlb, vma) \ - flush_tlb_range(vma, vma->vm_start, vma->vm_end) - -#define __tlb_remove_tlb_entry(tlb, pte, address) do { } while (0) - -/* - * Flush whole TLBs for MM - */ -#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm) - -#include - -#endif /* __ASSEMBLY__ */ - -#endif /* __ASM_SH64_TLB_H */ - diff -puN include/asm-sh64/tlbflush.h~git-sh /dev/null --- a/include/asm-sh64/tlbflush.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef __ASM_SH64_TLBFLUSH_H -#define __ASM_SH64_TLBFLUSH_H - -#include - -/* - * TLB flushing: - * - * - flush_tlb() flushes the current mm struct TLBs - * - flush_tlb_all() flushes all processes TLBs - * - flush_tlb_mm(mm) flushes the specified mm context TLB's - * - flush_tlb_page(vma, vmaddr) flushes one page - * - flush_tlb_range(mm, start, end) flushes a range of pages - * - */ - -extern void flush_tlb(void); -extern void flush_tlb_all(void); -extern void flush_tlb_mm(struct mm_struct *mm); -extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, - unsigned long end); -extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long page); - -extern void flush_tlb_kernel_range(unsigned long start, unsigned long end); - -#endif /* __ASM_SH64_TLBFLUSH_H */ - diff -puN include/asm-sh64/topology.h~git-sh /dev/null --- a/include/asm-sh64/topology.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __ASM_SH64_TOPOLOGY_H -#define __ASM_SH64_TOPOLOGY_H - -#include - -#endif /* __ASM_SH64_TOPOLOGY_H */ diff -puN include/asm-sh64/types.h~git-sh /dev/null --- a/include/asm-sh64/types.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef __ASM_SH64_TYPES_H -#define __ASM_SH64_TYPES_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/types.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#ifndef __ASSEMBLY__ - -typedef unsigned short umode_t; - -/* - * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the - * header files exported to user space - */ - -typedef __signed__ char __s8; -typedef unsigned char __u8; - -typedef __signed__ short __s16; -typedef unsigned short __u16; - -typedef __signed__ int __s32; -typedef unsigned int __u32; - -#if defined(__GNUC__) -__extension__ typedef __signed__ long long __s64; -__extension__ typedef unsigned long long __u64; -#endif - -#endif /* __ASSEMBLY__ */ - -/* - * These aren't exported outside the kernel to avoid name space clashes - */ -#ifdef __KERNEL__ - -#ifndef __ASSEMBLY__ - -typedef __signed__ char s8; -typedef unsigned char u8; - -typedef __signed__ short s16; -typedef unsigned short u16; - -typedef __signed__ int s32; -typedef unsigned int u32; - -typedef __signed__ long long s64; -typedef unsigned long long u64; - -/* DMA addresses come in generic and 64-bit flavours. */ - -#ifdef CONFIG_HIGHMEM64G -typedef u64 dma_addr_t; -#else -typedef u32 dma_addr_t; -#endif -typedef u64 dma64_addr_t; - -#endif /* __ASSEMBLY__ */ - -#define BITS_PER_LONG 32 - -#endif /* __KERNEL__ */ - -#endif /* __ASM_SH64_TYPES_H */ diff -puN include/asm-sh64/uaccess.h~git-sh /dev/null --- a/include/asm-sh64/uaccess.h +++ /dev/null @@ -1,316 +0,0 @@ -#ifndef __ASM_SH64_UACCESS_H -#define __ASM_SH64_UACCESS_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/uaccess.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003, 2004 Paul Mundt - * - * User space memory access functions - * - * Copyright (C) 1999 Niibe Yutaka - * - * Based on: - * MIPS implementation version 1.15 by - * Copyright (C) 1996, 1997, 1998 by Ralf Baechle - * and i386 version. - * - */ - -#include -#include - -#define VERIFY_READ 0 -#define VERIFY_WRITE 1 - -/* - * The fs value determines whether argument validity checking should be - * performed or not. If get_fs() == USER_DS, checking is performed, with - * get_fs() == KERNEL_DS, checking is bypassed. - * - * For historical reasons (Data Segment Register?), these macros are misnamed. - */ - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) - -#define KERNEL_DS MAKE_MM_SEG(0xFFFFFFFF) -#define USER_DS MAKE_MM_SEG(0x80000000) - -#define get_ds() (KERNEL_DS) -#define get_fs() (current_thread_info()->addr_limit) -#define set_fs(x) (current_thread_info()->addr_limit=(x)) - -#define segment_eq(a,b) ((a).seg == (b).seg) - -#define __addr_ok(addr) ((unsigned long)(addr) < (current_thread_info()->addr_limit.seg)) - -/* - * Uhhuh, this needs 33-bit arithmetic. We have a carry.. - * - * sum := addr + size; carry? --> flag = true; - * if (sum >= addr_limit) flag = true; - */ -#define __range_ok(addr,size) (((unsigned long) (addr) + (size) < (current_thread_info()->addr_limit.seg)) ? 0 : 1) - -#define access_ok(type,addr,size) (__range_ok(addr,size) == 0) -#define __access_ok(addr,size) (__range_ok(addr,size) == 0) - -/* - * Uh, these should become the main single-value transfer routines ... - * They automatically use the right size if we just have the right - * pointer type ... - * - * As MIPS uses the same address space for kernel and user data, we - * can just do these as direct assignments. - * - * Careful to not - * (a) re-use the arguments for side effects (sizeof is ok) - * (b) require any knowledge of processes at this stage - */ -#define put_user(x,ptr) __put_user_check((x),(ptr),sizeof(*(ptr))) -#define get_user(x,ptr) __get_user_check((x),(ptr),sizeof(*(ptr))) - -/* - * The "__xxx" versions do not do address space checking, useful when - * doing multiple accesses to the same area (the user has to do the - * checks by hand with "access_ok()") - */ -#define __put_user(x,ptr) __put_user_nocheck((x),(ptr),sizeof(*(ptr))) -#define __get_user(x,ptr) __get_user_nocheck((x),(ptr),sizeof(*(ptr))) - -/* - * The "xxx_ret" versions return constant specified in third argument, if - * something bad happens. These macros can be optimized for the - * case of just returning from the function xxx_ret is used. - */ - -#define put_user_ret(x,ptr,ret) ({ \ -if (put_user(x,ptr)) return ret; }) - -#define get_user_ret(x,ptr,ret) ({ \ -if (get_user(x,ptr)) return ret; }) - -#define __put_user_ret(x,ptr,ret) ({ \ -if (__put_user(x,ptr)) return ret; }) - -#define __get_user_ret(x,ptr,ret) ({ \ -if (__get_user(x,ptr)) return ret; }) - -struct __large_struct { unsigned long buf[100]; }; -#define __m(x) (*(struct __large_struct *)(x)) - -#define __get_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: \ - retval = __get_user_asm_b(x, ptr); \ - break; \ - case 2: \ - retval = __get_user_asm_w(x, ptr); \ - break; \ - case 4: \ - retval = __get_user_asm_l(x, ptr); \ - break; \ - case 8: \ - retval = __get_user_asm_q(x, ptr); \ - break; \ - default: \ - __get_user_unknown(); \ - break; \ - } \ -} while (0) - -#define __get_user_nocheck(x,ptr,size) \ -({ \ - long __gu_err, __gu_val; \ - __get_user_size((void *)&__gu_val, (long)(ptr), \ - (size), __gu_err); \ - (x) = (__typeof__(*(ptr)))__gu_val; \ - __gu_err; \ -}) - -#define __get_user_check(x,ptr,size) \ -({ \ - long __gu_addr = (long)(ptr); \ - long __gu_err = -EFAULT, __gu_val; \ - if (__access_ok(__gu_addr, (size))) \ - __get_user_size((void *)&__gu_val, __gu_addr, \ - (size), __gu_err); \ - (x) = (__typeof__(*(ptr))) __gu_val; \ - __gu_err; \ -}) - -extern long __get_user_asm_b(void *, long); -extern long __get_user_asm_w(void *, long); -extern long __get_user_asm_l(void *, long); -extern long __get_user_asm_q(void *, long); -extern void __get_user_unknown(void); - -#define __put_user_size(x,ptr,size,retval) \ -do { \ - retval = 0; \ - switch (size) { \ - case 1: \ - retval = __put_user_asm_b(x, ptr); \ - break; \ - case 2: \ - retval = __put_user_asm_w(x, ptr); \ - break; \ - case 4: \ - retval = __put_user_asm_l(x, ptr); \ - break; \ - case 8: \ - retval = __put_user_asm_q(x, ptr); \ - break; \ - default: \ - __put_user_unknown(); \ - } \ -} while (0) - -#define __put_user_nocheck(x,ptr,size) \ -({ \ - long __pu_err; \ - __typeof__(*(ptr)) __pu_val = (x); \ - __put_user_size((void *)&__pu_val, (long)(ptr), (size), __pu_err); \ - __pu_err; \ -}) - -#define __put_user_check(x,ptr,size) \ -({ \ - long __pu_err = -EFAULT; \ - long __pu_addr = (long)(ptr); \ - __typeof__(*(ptr)) __pu_val = (x); \ - \ - if (__access_ok(__pu_addr, (size))) \ - __put_user_size((void *)&__pu_val, __pu_addr, (size), __pu_err);\ - __pu_err; \ -}) - -extern long __put_user_asm_b(void *, long); -extern long __put_user_asm_w(void *, long); -extern long __put_user_asm_l(void *, long); -extern long __put_user_asm_q(void *, long); -extern void __put_user_unknown(void); - - -/* Generic arbitrary sized copy. */ -/* Return the number of bytes NOT copied */ -/* XXX: should be such that: 4byte and the rest. */ -extern __kernel_size_t __copy_user(void *__to, const void *__from, __kernel_size_t __n); - -#define copy_to_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_to, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, (void *) (from), __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - -#define copy_to_user_ret(to,from,n,retval) ({ \ -if (copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_to_user(to,from,n) \ - __copy_user((void *)(to), \ - (void *)(from), n) - -#define __copy_to_user_ret(to,from,n,retval) ({ \ -if (__copy_to_user(to,from,n)) \ - return retval; \ -}) - -#define copy_from_user(to,from,n) ({ \ -void *__copy_to = (void *) (to); \ -void *__copy_from = (void *) (from); \ -__kernel_size_t __copy_size = (__kernel_size_t) (n); \ -__kernel_size_t __copy_res; \ -if(__copy_size && __access_ok((unsigned long)__copy_from, __copy_size)) { \ -__copy_res = __copy_user(__copy_to, __copy_from, __copy_size); \ -} else __copy_res = __copy_size; \ -__copy_res; }) - -#define copy_from_user_ret(to,from,n,retval) ({ \ -if (copy_from_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_from_user(to,from,n) \ - __copy_user((void *)(to), \ - (void *)(from), n) - -#define __copy_from_user_ret(to,from,n,retval) ({ \ -if (__copy_from_user(to,from,n)) \ - return retval; \ -}) - -#define __copy_to_user_inatomic __copy_to_user -#define __copy_from_user_inatomic __copy_from_user - -/* XXX: Not sure it works well.. - should be such that: 4byte clear and the rest. */ -extern __kernel_size_t __clear_user(void *addr, __kernel_size_t size); - -#define clear_user(addr,n) ({ \ -void * __cl_addr = (addr); \ -unsigned long __cl_size = (n); \ -if (__cl_size && __access_ok(((unsigned long)(__cl_addr)), __cl_size)) \ -__cl_size = __clear_user(__cl_addr, __cl_size); \ -__cl_size; }) - -extern int __strncpy_from_user(unsigned long __dest, unsigned long __src, int __count); - -#define strncpy_from_user(dest,src,count) ({ \ -unsigned long __sfu_src = (unsigned long) (src); \ -int __sfu_count = (int) (count); \ -long __sfu_res = -EFAULT; \ -if(__access_ok(__sfu_src, __sfu_count)) { \ -__sfu_res = __strncpy_from_user((unsigned long) (dest), __sfu_src, __sfu_count); \ -} __sfu_res; }) - -#define strlen_user(str) strnlen_user(str, ~0UL >> 1) - -/* - * Return the size of a string (including the ending 0!) - */ -extern long __strnlen_user(const char *__s, long __n); - -static inline long strnlen_user(const char *s, long n) -{ - if (!__addr_ok(s)) - return 0; - else - return __strnlen_user(s, n); -} - -struct exception_table_entry -{ - unsigned long insn, fixup; -}; - -#define ARCH_HAS_SEARCH_EXTABLE - -/* If gcc inlines memset, it will use st.q instructions. Therefore, we need - kmalloc allocations to be 8-byte aligned. Without this, the alignment - becomes BYTE_PER_WORD i.e. only 4 (since sizeof(long)==sizeof(void*)==4 on - sh64 at the moment). */ -#define ARCH_KMALLOC_MINALIGN 8 - -/* - * We want 8-byte alignment for the slab caches as well, otherwise we have - * the same BYTES_PER_WORD (sizeof(void *)) min align in kmem_cache_create(). - */ -#define ARCH_SLAB_MINALIGN 8 - -/* Returns 0 if exception not found and fixup.unit otherwise. */ -extern unsigned long search_exception_table(unsigned long addr); -extern const struct exception_table_entry *search_exception_tables (unsigned long addr); - -#endif /* __ASM_SH64_UACCESS_H */ diff -puN include/asm-sh64/ucontext.h~git-sh /dev/null --- a/include/asm-sh64/ucontext.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef __ASM_SH64_UCONTEXT_H -#define __ASM_SH64_UCONTEXT_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/ucontext.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -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 /* __ASM_SH64_UCONTEXT_H */ diff -puN include/asm-sh64/unaligned.h~git-sh /dev/null --- a/include/asm-sh64/unaligned.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __ASM_SH64_UNALIGNED_H -#define __ASM_SH64_UNALIGNED_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/unaligned.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include - -#endif /* __ASM_SH64_UNALIGNED_H */ diff -puN include/asm-sh64/unistd.h~git-sh /dev/null --- a/include/asm-sh64/unistd.h +++ /dev/null @@ -1,417 +0,0 @@ -#ifndef __ASM_SH64_UNISTD_H -#define __ASM_SH64_UNISTD_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/unistd.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * Copyright (C) 2003 - 2007 Paul Mundt - * Copyright (C) 2004 Sean McGoogan - * - * 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 -#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 -#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 -#define __NR_statfs 99 -#define __NR_fstatfs 100 -#define __NR_ioperm 101 -#define __NR_socketcall 102 /* old implementation of socket systemcall */ -#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 -#define __NR_iopl 110 -#define __NR_vhangup 111 -#define __NR_idle 112 -#define __NR_vm86old 113 -#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 -#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 -#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_streams1 188 /* some people actually want it */ -#define __NR_streams2 189 /* some people actually want it */ -#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 - -/* Non-multiplexed socket family */ -#define __NR_socket 220 -#define __NR_bind 221 -#define __NR_connect 222 -#define __NR_listen 223 -#define __NR_accept 224 -#define __NR_getsockname 225 -#define __NR_getpeername 226 -#define __NR_socketpair 227 -#define __NR_send 228 -#define __NR_sendto 229 -#define __NR_recv 230 -#define __NR_recvfrom 231 -#define __NR_shutdown 232 -#define __NR_setsockopt 233 -#define __NR_getsockopt 234 -#define __NR_sendmsg 235 -#define __NR_recvmsg 236 - -/* Non-multiplexed IPC family */ -#define __NR_semop 237 -#define __NR_semget 238 -#define __NR_semctl 239 -#define __NR_msgsnd 240 -#define __NR_msgrcv 241 -#define __NR_msgget 242 -#define __NR_msgctl 243 -#if 0 -#define __NR_shmatcall 244 -#endif -#define __NR_shmdt 245 -#define __NR_shmget 246 -#define __NR_shmctl 247 - -#define __NR_getdents64 248 -#define __NR_fcntl64 249 -/* 223 is unused */ -#define __NR_gettid 252 -#define __NR_readahead 253 -#define __NR_setxattr 254 -#define __NR_lsetxattr 255 -#define __NR_fsetxattr 256 -#define __NR_getxattr 257 -#define __NR_lgetxattr 258 -#define __NR_fgetxattr 269 -#define __NR_listxattr 260 -#define __NR_llistxattr 261 -#define __NR_flistxattr 262 -#define __NR_removexattr 263 -#define __NR_lremovexattr 264 -#define __NR_fremovexattr 265 -#define __NR_tkill 266 -#define __NR_sendfile64 267 -#define __NR_futex 268 -#define __NR_sched_setaffinity 269 -#define __NR_sched_getaffinity 270 -#define __NR_set_thread_area 271 -#define __NR_get_thread_area 272 -#define __NR_io_setup 273 -#define __NR_io_destroy 274 -#define __NR_io_getevents 275 -#define __NR_io_submit 276 -#define __NR_io_cancel 277 -#define __NR_fadvise64 278 -#define __NR_exit_group 280 - -#define __NR_lookup_dcookie 281 -#define __NR_epoll_create 282 -#define __NR_epoll_ctl 283 -#define __NR_epoll_wait 284 -#define __NR_remap_file_pages 285 -#define __NR_set_tid_address 286 -#define __NR_timer_create 287 -#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 296 -#define __NR_fstatfs64 297 -#define __NR_tgkill 298 -#define __NR_utimes 299 -#define __NR_fadvise64_64 300 -#define __NR_vserver 301 -#define __NR_mbind 302 -#define __NR_get_mempolicy 303 -#define __NR_set_mempolicy 304 -#define __NR_mq_open 305 -#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 311 -#define __NR_waitid 312 -#define __NR_add_key 313 -#define __NR_request_key 314 -#define __NR_keyctl 315 -#define __NR_ioprio_set 316 -#define __NR_ioprio_get 317 -#define __NR_inotify_init 318 -#define __NR_inotify_add_watch 319 -#define __NR_inotify_rm_watch 320 -/* 321 is unused */ -#define __NR_migrate_pages 322 -#define __NR_openat 323 -#define __NR_mkdirat 324 -#define __NR_mknodat 325 -#define __NR_fchownat 326 -#define __NR_futimesat 327 -#define __NR_fstatat64 328 -#define __NR_unlinkat 329 -#define __NR_renameat 330 -#define __NR_linkat 331 -#define __NR_symlinkat 332 -#define __NR_readlinkat 333 -#define __NR_fchmodat 334 -#define __NR_faccessat 335 -#define __NR_pselect6 336 -#define __NR_ppoll 337 -#define __NR_unshare 338 -#define __NR_set_robust_list 339 -#define __NR_get_robust_list 340 -#define __NR_splice 341 -#define __NR_sync_file_range 342 -#define __NR_tee 343 -#define __NR_vmsplice 344 -#define __NR_move_pages 345 -#define __NR_getcpu 346 -#define __NR_epoll_pwait 347 -#define __NR_utimensat 348 -#define __NR_signalfd 349 -#define __NR_timerfd 350 -#define __NR_eventfd 351 -#define __NR_fallocate 352 - -#ifdef __KERNEL__ - -#define NR_syscalls 353 - -#define __ARCH_WANT_IPC_PARSE_VERSION -#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_PAUSE -#define __ARCH_WANT_SYS_SGETMASK -#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_RT_SIGACTION - -/* - * "Conditional" syscalls - * - * What we want is __attribute__((weak,alias("sys_ni_syscall"))), - * but it doesn't work on all toolchains, so we just do it by hand - */ -#ifndef cond_syscall -#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall") -#endif - -#endif /* __KERNEL__ */ -#endif /* __ASM_SH64_UNISTD_H */ diff -puN include/asm-sh64/user.h~git-sh /dev/null --- a/include/asm-sh64/user.h +++ /dev/null @@ -1,70 +0,0 @@ -#ifndef __ASM_SH64_USER_H -#define __ASM_SH64_USER_H - -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * include/asm-sh64/user.h - * - * Copyright (C) 2000, 2001 Paolo Alberelli - * - */ - -#include -#include -#include - -/* - * 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). The 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 handy at some point. All of the registers - * are stored as part of the upage. The upage should always be - * only one page long. - * data: The data segment follows next. We use current->end_text to - * current->brk to pick up all of the user variables, plus any memory - * that may have been sbrk'ed. 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 usp to - * current->start_stack, so we round each of these in order to be able - * to write an integer number of pages. - */ - -struct user_fpu_struct { - unsigned long long fp_regs[32]; - unsigned int fpscr; -}; - -struct user { - struct pt_regs regs; /* entire machine state */ - struct user_fpu_struct fpu; /* Math Co-processor registers */ - int u_fpvalid; /* True if math co-processor being used */ - size_t u_tsize; /* text size (pages) */ - size_t u_dsize; /* data size (pages) */ - size_t u_ssize; /* stack size (pages) */ - unsigned long start_code; /* text starting address */ - unsigned long start_data; /* data starting address */ - unsigned long start_stack; /* stack starting address */ - long int signal; /* signal causing core dump */ - struct regs * u_ar0; /* help gdb find registers */ - struct user_fpu_struct* u_fpstate; /* Math Co-processor pointer */ - unsigned long magic; /* identifies a core file */ - char u_comm[32]; /* user command name */ -}; - -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.start_data) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif /* __ASM_SH64_USER_H */ diff -puN init/Kconfig~git-sh init/Kconfig --- a/init/Kconfig~git-sh +++ a/init/Kconfig @@ -238,7 +238,7 @@ config AUDIT config AUDITSYSCALL bool "Enable system-call auditing support" - depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64) + depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64|| SUPERH) default y if SECURITY_SELINUX help Enable low-overhead system-call auditing infrastructure that diff -puN mm/Kconfig~git-sh mm/Kconfig --- a/mm/Kconfig~git-sh +++ a/mm/Kconfig @@ -187,7 +187,7 @@ config BOUNCE config NR_QUICK int depends on QUICKLIST - default "2" if (SUPERH && !SUPERH64) + default "2" if SUPERH default "1" config VIRT_TO_BUS diff -puN /dev/null /dev/null _