diff options
| author | Chris Zankel <chris@zankel.net> | 2014-08-18 20:30:24 -0400 |
|---|---|---|
| committer | Chris Zankel <chris@zankel.net> | 2014-08-18 20:30:24 -0400 |
| commit | e792290be763932d1b8cdf8a36d7015482a49d07 (patch) | |
| tree | 2aec72e1556ef099ff9bd535d21d4477e1db9ddb | |
| parent | 7d1311b93e58ed55f3a31cc8f94c4b8fe988a2b9 (diff) | |
| parent | 9184289c979e78ce466993b53fc951633441e571 (diff) | |
Merge tag 'xtensa-for-next-20140815' into for_next
Xtensa improvements for 3.17:
- support highmem on cores with aliasing data cache. Enable highmem on kc705
by default;
- simplify addition of new core variants (no need to modify Kconfig /
Makefiles);
- improve robustness of unaligned access handler and its interaction with
window overflow/underflow exception handlers;
- deprecate atomic and spill registers syscalls;
- clean up Kconfig: remove orphan MATH_EMULATION, sort 'select' statements;
- wire up renameat2 syscall.
Various fixes:
- fix address checks in dma_{alloc,free}_coherent (runtime BUG);
- fix access to THREAD_RA/THREAD_SP/THREAD_DS (debug build breakage);
- fix TLBTEMP_BASE_2 region handling in fast_second_level_miss (runtime
unrecoverable exception);
- fix a6 and a7 handling in fast_syscall_xtensa (runtime userspace register
clobbering);
- fix kernel/user jump out of fast_unaligned (potential runtime unrecoverable
exception);
- replace termios IOCTL code definitions with constants (userspace build
breakage).
Signed-off-by: Chris Zankel <chris@zankel.net>
| -rw-r--r-- | arch/xtensa/Kconfig | 92 | ||||
| -rw-r--r-- | arch/xtensa/Makefile | 7 | ||||
| -rw-r--r-- | arch/xtensa/boot/dts/kc705.dts | 5 | ||||
| -rw-r--r-- | arch/xtensa/configs/common_defconfig | 1 | ||||
| -rw-r--r-- | arch/xtensa/configs/iss_defconfig | 3 | ||||
| -rw-r--r-- | arch/xtensa/configs/s6105_defconfig | 1 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/cacheflush.h | 2 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/fixmap.h | 30 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/highmem.h | 40 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/page.h | 14 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/pgtable.h | 7 | ||||
| -rw-r--r-- | arch/xtensa/include/asm/uaccess.h | 5 | ||||
| -rw-r--r-- | arch/xtensa/include/uapi/asm/ioctls.h | 19 | ||||
| -rw-r--r-- | arch/xtensa/include/uapi/asm/unistd.h | 5 | ||||
| -rw-r--r-- | arch/xtensa/kernel/align.S | 128 | ||||
| -rw-r--r-- | arch/xtensa/kernel/entry.S | 54 | ||||
| -rw-r--r-- | arch/xtensa/kernel/pci-dma.c | 12 | ||||
| -rw-r--r-- | arch/xtensa/kernel/traps.c | 5 | ||||
| -rw-r--r-- | arch/xtensa/kernel/vectors.S | 8 | ||||
| -rw-r--r-- | arch/xtensa/kernel/vmlinux.lds.S | 4 | ||||
| -rw-r--r-- | arch/xtensa/mm/cache.c | 77 | ||||
| -rw-r--r-- | arch/xtensa/mm/highmem.c | 41 | ||||
| -rw-r--r-- | arch/xtensa/mm/misc.S | 116 | ||||
| -rw-r--r-- | arch/xtensa/mm/mmu.c | 38 |
24 files changed, 497 insertions, 217 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 3a617af60d46..49c6c3d94449 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
| @@ -4,24 +4,23 @@ config ZONE_DMA | |||
| 4 | config XTENSA | 4 | config XTENSA |
| 5 | def_bool y | 5 | def_bool y |
| 6 | select ARCH_WANT_FRAME_POINTERS | 6 | select ARCH_WANT_FRAME_POINTERS |
| 7 | select HAVE_IDE | ||
| 8 | select GENERIC_ATOMIC64 | ||
| 9 | select GENERIC_CLOCKEVENTS | ||
| 10 | select VIRT_TO_BUS | ||
| 11 | select GENERIC_IRQ_SHOW | ||
| 12 | select GENERIC_SCHED_CLOCK | ||
| 13 | select MODULES_USE_ELF_RELA | ||
| 14 | select GENERIC_PCI_IOMAP | ||
| 15 | select ARCH_WANT_IPC_PARSE_VERSION | 7 | select ARCH_WANT_IPC_PARSE_VERSION |
| 16 | select ARCH_WANT_OPTIONAL_GPIOLIB | 8 | select ARCH_WANT_OPTIONAL_GPIOLIB |
| 17 | select BUILDTIME_EXTABLE_SORT | 9 | select BUILDTIME_EXTABLE_SORT |
| 18 | select CLONE_BACKWARDS | 10 | select CLONE_BACKWARDS |
| 19 | select IRQ_DOMAIN | 11 | select COMMON_CLK |
| 20 | select HAVE_OPROFILE | 12 | select GENERIC_ATOMIC64 |
| 13 | select GENERIC_CLOCKEVENTS | ||
| 14 | select GENERIC_IRQ_SHOW | ||
| 15 | select GENERIC_PCI_IOMAP | ||
| 16 | select GENERIC_SCHED_CLOCK | ||
| 21 | select HAVE_FUNCTION_TRACER | 17 | select HAVE_FUNCTION_TRACER |
| 22 | select HAVE_IRQ_TIME_ACCOUNTING | 18 | select HAVE_IRQ_TIME_ACCOUNTING |
| 19 | select HAVE_OPROFILE | ||
| 23 | select HAVE_PERF_EVENTS | 20 | select HAVE_PERF_EVENTS |
| 24 | select COMMON_CLK | 21 | select IRQ_DOMAIN |
| 22 | select MODULES_USE_ELF_RELA | ||
| 23 | select VIRT_TO_BUS | ||
| 25 | help | 24 | help |
| 26 | Xtensa processors are 32-bit RISC machines designed by Tensilica | 25 | Xtensa processors are 32-bit RISC machines designed by Tensilica |
| 27 | primarily for embedded systems. These processors are both | 26 | primarily for embedded systems. These processors are both |
| @@ -62,7 +61,9 @@ config TRACE_IRQFLAGS_SUPPORT | |||
| 62 | def_bool y | 61 | def_bool y |
| 63 | 62 | ||
| 64 | config MMU | 63 | config MMU |
| 65 | def_bool n | 64 | bool |
| 65 | default n if !XTENSA_VARIANT_CUSTOM | ||
| 66 | default XTENSA_VARIANT_MMU if XTENSA_VARIANT_CUSTOM | ||
| 66 | 67 | ||
| 67 | config VARIANT_IRQ_SWITCH | 68 | config VARIANT_IRQ_SWITCH |
| 68 | def_bool n | 69 | def_bool n |
| @@ -102,8 +103,40 @@ config XTENSA_VARIANT_S6000 | |||
| 102 | select VARIANT_IRQ_SWITCH | 103 | select VARIANT_IRQ_SWITCH |
| 103 | select ARCH_REQUIRE_GPIOLIB | 104 | select ARCH_REQUIRE_GPIOLIB |
| 104 | select XTENSA_CALIBRATE_CCOUNT | 105 | select XTENSA_CALIBRATE_CCOUNT |
| 106 | |||
| 107 | config XTENSA_VARIANT_CUSTOM | ||
| 108 | bool "Custom Xtensa processor configuration" | ||
| 109 | select MAY_HAVE_SMP | ||
| 110 | select HAVE_XTENSA_GPIO32 | ||
| 111 | help | ||
| 112 | Select this variant to use a custom Xtensa processor configuration. | ||
| 113 | You will be prompted for a processor variant CORENAME. | ||
| 105 | endchoice | 114 | endchoice |
| 106 | 115 | ||
| 116 | config XTENSA_VARIANT_CUSTOM_NAME | ||
| 117 | string "Xtensa Processor Custom Core Variant Name" | ||
| 118 | depends on XTENSA_VARIANT_CUSTOM | ||
| 119 | help | ||
| 120 | Provide the name of a custom Xtensa processor variant. | ||
| 121 | This CORENAME selects arch/xtensa/variant/CORENAME. | ||
| 122 | Dont forget you have to select MMU if you have one. | ||
| 123 | |||
| 124 | config XTENSA_VARIANT_NAME | ||
| 125 | string | ||
| 126 | default "dc232b" if XTENSA_VARIANT_DC232B | ||
| 127 | default "dc233c" if XTENSA_VARIANT_DC233C | ||
| 128 | default "fsf" if XTENSA_VARIANT_FSF | ||
| 129 | default "s6000" if XTENSA_VARIANT_S6000 | ||
| 130 | default XTENSA_VARIANT_CUSTOM_NAME if XTENSA_VARIANT_CUSTOM | ||
| 131 | |||
| 132 | config XTENSA_VARIANT_MMU | ||
| 133 | bool "Core variant has a Full MMU (TLB, Pages, Protection, etc)" | ||
| 134 | depends on XTENSA_VARIANT_CUSTOM | ||
| 135 | default y | ||
| 136 | help | ||
| 137 | Build a Conventional Kernel with full MMU support, | ||
| 138 | ie: it supports a TLB with auto-loading, page protection. | ||
| 139 | |||
| 107 | config XTENSA_UNALIGNED_USER | 140 | config XTENSA_UNALIGNED_USER |
| 108 | bool "Unaligned memory access in use space" | 141 | bool "Unaligned memory access in use space" |
| 109 | help | 142 | help |
| @@ -156,13 +189,9 @@ config HOTPLUG_CPU | |||
| 156 | 189 | ||
| 157 | Say N if you want to disable CPU hotplug. | 190 | Say N if you want to disable CPU hotplug. |
| 158 | 191 | ||
| 159 | config MATH_EMULATION | ||
| 160 | bool "Math emulation" | ||
| 161 | help | ||
| 162 | Can we use information of configuration file? | ||
| 163 | |||
| 164 | config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | 192 | config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX |
| 165 | bool "Initialize Xtensa MMU inside the Linux kernel code" | 193 | bool "Initialize Xtensa MMU inside the Linux kernel code" |
| 194 | depends on MMU | ||
| 166 | default y | 195 | default y |
| 167 | help | 196 | help |
| 168 | Earlier version initialized the MMU in the exception vector | 197 | Earlier version initialized the MMU in the exception vector |
| @@ -192,6 +221,7 @@ config INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | |||
| 192 | 221 | ||
| 193 | config HIGHMEM | 222 | config HIGHMEM |
| 194 | bool "High Memory Support" | 223 | bool "High Memory Support" |
| 224 | depends on MMU | ||
| 195 | help | 225 | help |
| 196 | Linux can use the full amount of RAM in the system by | 226 | Linux can use the full amount of RAM in the system by |
| 197 | default. However, the default MMUv2 setup only maps the | 227 | default. However, the default MMUv2 setup only maps the |
| @@ -208,6 +238,32 @@ config HIGHMEM | |||
| 208 | 238 | ||
| 209 | If unsure, say Y. | 239 | If unsure, say Y. |
| 210 | 240 | ||
| 241 | config FAST_SYSCALL_XTENSA | ||
| 242 | bool "Enable fast atomic syscalls" | ||
| 243 | default n | ||
| 244 | help | ||
| 245 | fast_syscall_xtensa is a syscall that can make atomic operations | ||
| 246 | on UP kernel when processor has no s32c1i support. | ||
| 247 | |||
| 248 | This syscall is deprecated. It may have issues when called with | ||
| 249 | invalid arguments. It is provided only for backwards compatibility. | ||
| 250 | Only enable it if your userspace software requires it. | ||
| 251 | |||
| 252 | If unsure, say N. | ||
| 253 | |||
| 254 | config FAST_SYSCALL_SPILL_REGISTERS | ||
| 255 | bool "Enable spill registers syscall" | ||
| 256 | default n | ||
| 257 | help | ||
| 258 | fast_syscall_spill_registers is a syscall that spills all active | ||
| 259 | register windows of a calling userspace task onto its stack. | ||
| 260 | |||
| 261 | This syscall is deprecated. It may have issues when called with | ||
| 262 | invalid arguments. It is provided only for backwards compatibility. | ||
| 263 | Only enable it if your userspace software requires it. | ||
| 264 | |||
| 265 | If unsure, say N. | ||
| 266 | |||
| 211 | endmenu | 267 | endmenu |
| 212 | 268 | ||
| 213 | config XTENSA_CALIBRATE_CCOUNT | 269 | config XTENSA_CALIBRATE_CCOUNT |
| @@ -250,12 +306,14 @@ config XTENSA_PLATFORM_ISS | |||
| 250 | 306 | ||
| 251 | config XTENSA_PLATFORM_XT2000 | 307 | config XTENSA_PLATFORM_XT2000 |
| 252 | bool "XT2000" | 308 | bool "XT2000" |
| 309 | select HAVE_IDE | ||
| 253 | help | 310 | help |
| 254 | XT2000 is the name of Tensilica's feature-rich emulation platform. | 311 | XT2000 is the name of Tensilica's feature-rich emulation platform. |
| 255 | This hardware is capable of running a full Linux distribution. | 312 | This hardware is capable of running a full Linux distribution. |
| 256 | 313 | ||
| 257 | config XTENSA_PLATFORM_S6105 | 314 | config XTENSA_PLATFORM_S6105 |
| 258 | bool "S6105" | 315 | bool "S6105" |
| 316 | select HAVE_IDE | ||
| 259 | select SERIAL_CONSOLE | 317 | select SERIAL_CONSOLE |
| 260 | select NO_IOPORT_MAP | 318 | select NO_IOPORT_MAP |
| 261 | 319 | ||
diff --git a/arch/xtensa/Makefile b/arch/xtensa/Makefile index 81250ece3062..472533064b46 100644 --- a/arch/xtensa/Makefile +++ b/arch/xtensa/Makefile | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | # for more details. | 4 | # for more details. |
| 5 | # | 5 | # |
| 6 | # Copyright (C) 2001 - 2005 Tensilica Inc. | 6 | # Copyright (C) 2001 - 2005 Tensilica Inc. |
| 7 | # Copyright (C) 2014 Cadence Design Systems Inc. | ||
| 7 | # | 8 | # |
| 8 | # This file is included by the global makefile so that you can add your own | 9 | # This file is included by the global makefile so that you can add your own |
| 9 | # architecture-specific flags and dependencies. Remember to do have actions | 10 | # architecture-specific flags and dependencies. Remember to do have actions |
| @@ -13,11 +14,7 @@ | |||
| 13 | # Core configuration. | 14 | # Core configuration. |
| 14 | # (Use VAR=<xtensa_config> to use another default compiler.) | 15 | # (Use VAR=<xtensa_config> to use another default compiler.) |
| 15 | 16 | ||
| 16 | variant-$(CONFIG_XTENSA_VARIANT_FSF) := fsf | 17 | variant-y := $(patsubst "%",%,$(CONFIG_XTENSA_VARIANT_NAME)) |
| 17 | variant-$(CONFIG_XTENSA_VARIANT_DC232B) := dc232b | ||
| 18 | variant-$(CONFIG_XTENSA_VARIANT_DC233C) := dc233c | ||
| 19 | variant-$(CONFIG_XTENSA_VARIANT_S6000) := s6000 | ||
| 20 | variant-$(CONFIG_XTENSA_VARIANT_LINUX_CUSTOM) := custom | ||
| 21 | 18 | ||
| 22 | VARIANT = $(variant-y) | 19 | VARIANT = $(variant-y) |
| 23 | export VARIANT | 20 | export VARIANT |
diff --git a/arch/xtensa/boot/dts/kc705.dts b/arch/xtensa/boot/dts/kc705.dts index 742a347be67a..c4d17a34ab86 100644 --- a/arch/xtensa/boot/dts/kc705.dts +++ b/arch/xtensa/boot/dts/kc705.dts | |||
| @@ -4,8 +4,11 @@ | |||
| 4 | 4 | ||
| 5 | / { | 5 | / { |
| 6 | compatible = "cdns,xtensa-kc705"; | 6 | compatible = "cdns,xtensa-kc705"; |
| 7 | chosen { | ||
| 8 | bootargs = "earlycon=uart8250,mmio32,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000"; | ||
| 9 | }; | ||
| 7 | memory@0 { | 10 | memory@0 { |
| 8 | device_type = "memory"; | 11 | device_type = "memory"; |
| 9 | reg = <0x00000000 0x08000000>; | 12 | reg = <0x00000000 0x38000000>; |
| 10 | }; | 13 | }; |
| 11 | }; | 14 | }; |
diff --git a/arch/xtensa/configs/common_defconfig b/arch/xtensa/configs/common_defconfig index f6000fe05119..721df1214bc3 100644 --- a/arch/xtensa/configs/common_defconfig +++ b/arch/xtensa/configs/common_defconfig | |||
| @@ -66,7 +66,6 @@ CONFIG_XTENSA_ARCH_LINUX_BE=y | |||
| 66 | CONFIG_MMU=y | 66 | CONFIG_MMU=y |
| 67 | # CONFIG_XTENSA_UNALIGNED_USER is not set | 67 | # CONFIG_XTENSA_UNALIGNED_USER is not set |
| 68 | # CONFIG_PREEMPT is not set | 68 | # CONFIG_PREEMPT is not set |
| 69 | # CONFIG_MATH_EMULATION is not set | ||
| 70 | # CONFIG_HIGHMEM is not set | 69 | # CONFIG_HIGHMEM is not set |
| 71 | 70 | ||
| 72 | # | 71 | # |
diff --git a/arch/xtensa/configs/iss_defconfig b/arch/xtensa/configs/iss_defconfig index 1493c68352d1..b966baf82cae 100644 --- a/arch/xtensa/configs/iss_defconfig +++ b/arch/xtensa/configs/iss_defconfig | |||
| @@ -146,7 +146,6 @@ CONFIG_XTENSA_VARIANT_FSF=y | |||
| 146 | # CONFIG_XTENSA_VARIANT_S6000 is not set | 146 | # CONFIG_XTENSA_VARIANT_S6000 is not set |
| 147 | # CONFIG_XTENSA_UNALIGNED_USER is not set | 147 | # CONFIG_XTENSA_UNALIGNED_USER is not set |
| 148 | # CONFIG_PREEMPT is not set | 148 | # CONFIG_PREEMPT is not set |
| 149 | # CONFIG_MATH_EMULATION is not set | ||
| 150 | CONFIG_XTENSA_CALIBRATE_CCOUNT=y | 149 | CONFIG_XTENSA_CALIBRATE_CCOUNT=y |
| 151 | CONFIG_SERIAL_CONSOLE=y | 150 | CONFIG_SERIAL_CONSOLE=y |
| 152 | CONFIG_XTENSA_ISS_NETWORK=y | 151 | CONFIG_XTENSA_ISS_NETWORK=y |
| @@ -308,7 +307,7 @@ CONFIG_MISC_DEVICES=y | |||
| 308 | # EEPROM support | 307 | # EEPROM support |
| 309 | # | 308 | # |
| 310 | # CONFIG_EEPROM_93CX6 is not set | 309 | # CONFIG_EEPROM_93CX6 is not set |
| 311 | CONFIG_HAVE_IDE=y | 310 | # CONFIG_HAVE_IDE is not set |
| 312 | # CONFIG_IDE is not set | 311 | # CONFIG_IDE is not set |
| 313 | 312 | ||
| 314 | # | 313 | # |
diff --git a/arch/xtensa/configs/s6105_defconfig b/arch/xtensa/configs/s6105_defconfig index 12a492ab6d17..9471265b8ca6 100644 --- a/arch/xtensa/configs/s6105_defconfig +++ b/arch/xtensa/configs/s6105_defconfig | |||
| @@ -109,7 +109,6 @@ CONFIG_VARIANT_IRQ_SWITCH=y | |||
| 109 | CONFIG_XTENSA_VARIANT_S6000=y | 109 | CONFIG_XTENSA_VARIANT_S6000=y |
| 110 | # CONFIG_XTENSA_UNALIGNED_USER is not set | 110 | # CONFIG_XTENSA_UNALIGNED_USER is not set |
| 111 | CONFIG_PREEMPT=y | 111 | CONFIG_PREEMPT=y |
| 112 | # CONFIG_MATH_EMULATION is not set | ||
| 113 | # CONFIG_HIGHMEM is not set | 112 | # CONFIG_HIGHMEM is not set |
| 114 | CONFIG_XTENSA_CALIBRATE_CCOUNT=y | 113 | CONFIG_XTENSA_CALIBRATE_CCOUNT=y |
| 115 | CONFIG_SERIAL_CONSOLE=y | 114 | CONFIG_SERIAL_CONSOLE=y |
diff --git a/arch/xtensa/include/asm/cacheflush.h b/arch/xtensa/include/asm/cacheflush.h index 555a98a18453..e72aaca7a77f 100644 --- a/arch/xtensa/include/asm/cacheflush.h +++ b/arch/xtensa/include/asm/cacheflush.h | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | * specials for cache aliasing: | 37 | * specials for cache aliasing: |
| 38 | * | 38 | * |
| 39 | * __flush_invalidate_dcache_page_alias(vaddr,paddr) | 39 | * __flush_invalidate_dcache_page_alias(vaddr,paddr) |
| 40 | * __invalidate_dcache_page_alias(vaddr,paddr) | ||
| 40 | * __invalidate_icache_page_alias(vaddr,paddr) | 41 | * __invalidate_icache_page_alias(vaddr,paddr) |
| 41 | */ | 42 | */ |
| 42 | 43 | ||
| @@ -62,6 +63,7 @@ extern void __flush_invalidate_dcache_range(unsigned long, unsigned long); | |||
| 62 | 63 | ||
| 63 | #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE) | 64 | #if defined(CONFIG_MMU) && (DCACHE_WAY_SIZE > PAGE_SIZE) |
| 64 | extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long); | 65 | extern void __flush_invalidate_dcache_page_alias(unsigned long, unsigned long); |
| 66 | extern void __invalidate_dcache_page_alias(unsigned long, unsigned long); | ||
| 65 | #else | 67 | #else |
| 66 | static inline void __flush_invalidate_dcache_page_alias(unsigned long virt, | 68 | static inline void __flush_invalidate_dcache_page_alias(unsigned long virt, |
| 67 | unsigned long phys) { } | 69 | unsigned long phys) { } |
diff --git a/arch/xtensa/include/asm/fixmap.h b/arch/xtensa/include/asm/fixmap.h index 9f6c33d0428a..62b507deea9d 100644 --- a/arch/xtensa/include/asm/fixmap.h +++ b/arch/xtensa/include/asm/fixmap.h | |||
| @@ -23,8 +23,8 @@ | |||
| 23 | * Here we define all the compile-time 'special' virtual | 23 | * Here we define all the compile-time 'special' virtual |
| 24 | * addresses. The point is to have a constant address at | 24 | * addresses. The point is to have a constant address at |
| 25 | * compile time, but to set the physical address only | 25 | * compile time, but to set the physical address only |
| 26 | * in the boot process. We allocate these special addresses | 26 | * in the boot process. We allocate these special addresses |
| 27 | * from the end of the consistent memory region backwards. | 27 | * from the start of the consistent memory region upwards. |
| 28 | * Also this lets us do fail-safe vmalloc(), we | 28 | * Also this lets us do fail-safe vmalloc(), we |
| 29 | * can guarantee that these special addresses and | 29 | * can guarantee that these special addresses and |
| 30 | * vmalloc()-ed addresses never overlap. | 30 | * vmalloc()-ed addresses never overlap. |
| @@ -38,7 +38,8 @@ enum fixed_addresses { | |||
| 38 | #ifdef CONFIG_HIGHMEM | 38 | #ifdef CONFIG_HIGHMEM |
| 39 | /* reserved pte's for temporary kernel mappings */ | 39 | /* reserved pte's for temporary kernel mappings */ |
| 40 | FIX_KMAP_BEGIN, | 40 | FIX_KMAP_BEGIN, |
| 41 | FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS) - 1, | 41 | FIX_KMAP_END = FIX_KMAP_BEGIN + |
| 42 | (KM_TYPE_NR * NR_CPUS * DCACHE_N_COLORS) - 1, | ||
| 42 | #endif | 43 | #endif |
| 43 | __end_of_fixed_addresses | 44 | __end_of_fixed_addresses |
| 44 | }; | 45 | }; |
| @@ -47,7 +48,28 @@ enum fixed_addresses { | |||
| 47 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) | 48 | #define FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT) |
| 48 | #define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK) | 49 | #define FIXADDR_START ((FIXADDR_TOP - FIXADDR_SIZE) & PMD_MASK) |
| 49 | 50 | ||
| 50 | #include <asm-generic/fixmap.h> | 51 | #define __fix_to_virt(x) (FIXADDR_START + ((x) << PAGE_SHIFT)) |
| 52 | #define __virt_to_fix(x) (((x) - FIXADDR_START) >> PAGE_SHIFT) | ||
| 53 | |||
| 54 | #ifndef __ASSEMBLY__ | ||
| 55 | /* | ||
| 56 | * 'index to address' translation. If anyone tries to use the idx | ||
| 57 | * directly without translation, we catch the bug with a NULL-deference | ||
| 58 | * kernel oops. Illegal ranges of incoming indices are caught too. | ||
| 59 | */ | ||
| 60 | static __always_inline unsigned long fix_to_virt(const unsigned int idx) | ||
| 61 | { | ||
| 62 | BUILD_BUG_ON(idx >= __end_of_fixed_addresses); | ||
| 63 | return __fix_to_virt(idx); | ||
| 64 | } | ||
| 65 | |||
| 66 | static inline unsigned long virt_to_fix(const unsigned long vaddr) | ||
| 67 | { | ||
| 68 | BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START); | ||
| 69 | return __virt_to_fix(vaddr); | ||
| 70 | } | ||
| 71 | |||
| 72 | #endif | ||
| 51 | 73 | ||
| 52 | #define kmap_get_fixmap_pte(vaddr) \ | 74 | #define kmap_get_fixmap_pte(vaddr) \ |
| 53 | pte_offset_kernel( \ | 75 | pte_offset_kernel( \ |
diff --git a/arch/xtensa/include/asm/highmem.h b/arch/xtensa/include/asm/highmem.h index 2653ef5d55f1..2c7901edffaf 100644 --- a/arch/xtensa/include/asm/highmem.h +++ b/arch/xtensa/include/asm/highmem.h | |||
| @@ -12,19 +12,55 @@ | |||
| 12 | #ifndef _XTENSA_HIGHMEM_H | 12 | #ifndef _XTENSA_HIGHMEM_H |
| 13 | #define _XTENSA_HIGHMEM_H | 13 | #define _XTENSA_HIGHMEM_H |
| 14 | 14 | ||
| 15 | #include <linux/wait.h> | ||
| 15 | #include <asm/cacheflush.h> | 16 | #include <asm/cacheflush.h> |
| 16 | #include <asm/fixmap.h> | 17 | #include <asm/fixmap.h> |
| 17 | #include <asm/kmap_types.h> | 18 | #include <asm/kmap_types.h> |
| 18 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
| 19 | 20 | ||
| 20 | #define PKMAP_BASE (FIXADDR_START - PMD_SIZE) | 21 | #define PKMAP_BASE ((FIXADDR_START - \ |
| 21 | #define LAST_PKMAP PTRS_PER_PTE | 22 | (LAST_PKMAP + 1) * PAGE_SIZE) & PMD_MASK) |
| 23 | #define LAST_PKMAP (PTRS_PER_PTE * DCACHE_N_COLORS) | ||
| 22 | #define LAST_PKMAP_MASK (LAST_PKMAP - 1) | 24 | #define LAST_PKMAP_MASK (LAST_PKMAP - 1) |
| 23 | #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) | 25 | #define PKMAP_NR(virt) (((virt) - PKMAP_BASE) >> PAGE_SHIFT) |
| 24 | #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) | 26 | #define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT)) |
| 25 | 27 | ||
| 26 | #define kmap_prot PAGE_KERNEL | 28 | #define kmap_prot PAGE_KERNEL |
| 27 | 29 | ||
| 30 | #if DCACHE_WAY_SIZE > PAGE_SIZE | ||
| 31 | #define get_pkmap_color get_pkmap_color | ||
| 32 | static inline int get_pkmap_color(struct page *page) | ||
| 33 | { | ||
| 34 | return DCACHE_ALIAS(page_to_phys(page)); | ||
| 35 | } | ||
| 36 | |||
| 37 | extern unsigned int last_pkmap_nr_arr[]; | ||
| 38 | |||
| 39 | static inline unsigned int get_next_pkmap_nr(unsigned int color) | ||
| 40 | { | ||
| 41 | last_pkmap_nr_arr[color] = | ||
| 42 | (last_pkmap_nr_arr[color] + DCACHE_N_COLORS) & LAST_PKMAP_MASK; | ||
| 43 | return last_pkmap_nr_arr[color] + color; | ||
| 44 | } | ||
| 45 | |||
| 46 | static inline int no_more_pkmaps(unsigned int pkmap_nr, unsigned int color) | ||
| 47 | { | ||
| 48 | return pkmap_nr < DCACHE_N_COLORS; | ||
| 49 | } | ||
| 50 | |||
| 51 | static inline int get_pkmap_entries_count(unsigned int color) | ||
| 52 | { | ||
| 53 | return LAST_PKMAP / DCACHE_N_COLORS; | ||
| 54 | } | ||
| 55 | |||
| 56 | extern wait_queue_head_t pkmap_map_wait_arr[]; | ||
| 57 | |||
| 58 | static inline wait_queue_head_t *get_pkmap_wait_queue_head(unsigned int color) | ||
| 59 | { | ||
| 60 | return pkmap_map_wait_arr + color; | ||
| 61 | } | ||
| 62 | #endif | ||
| 63 | |||
| 28 | extern pte_t *pkmap_page_table; | 64 | extern pte_t *pkmap_page_table; |
| 29 | 65 | ||
| 30 | void *kmap_high(struct page *page); | 66 | void *kmap_high(struct page *page); |
diff --git a/arch/xtensa/include/asm/page.h b/arch/xtensa/include/asm/page.h index 47f582333f6b..abe24c6f8b2f 100644 --- a/arch/xtensa/include/asm/page.h +++ b/arch/xtensa/include/asm/page.h | |||
| @@ -78,7 +78,9 @@ | |||
| 78 | # define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0) | 78 | # define DCACHE_ALIAS_EQ(a,b) ((((a) ^ (b)) & DCACHE_ALIAS_MASK) == 0) |
| 79 | #else | 79 | #else |
| 80 | # define DCACHE_ALIAS_ORDER 0 | 80 | # define DCACHE_ALIAS_ORDER 0 |
| 81 | # define DCACHE_ALIAS(a) ((void)(a), 0) | ||
| 81 | #endif | 82 | #endif |
| 83 | #define DCACHE_N_COLORS (1 << DCACHE_ALIAS_ORDER) | ||
| 82 | 84 | ||
| 83 | #if ICACHE_WAY_SIZE > PAGE_SIZE | 85 | #if ICACHE_WAY_SIZE > PAGE_SIZE |
| 84 | # define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT) | 86 | # define ICACHE_ALIAS_ORDER (ICACHE_WAY_SHIFT - PAGE_SHIFT) |
| @@ -134,6 +136,7 @@ static inline __attribute_const__ int get_order(unsigned long size) | |||
| 134 | #endif | 136 | #endif |
| 135 | 137 | ||
| 136 | struct page; | 138 | struct page; |
| 139 | struct vm_area_struct; | ||
| 137 | extern void clear_page(void *page); | 140 | extern void clear_page(void *page); |
| 138 | extern void copy_page(void *to, void *from); | 141 | extern void copy_page(void *to, void *from); |
| 139 | 142 | ||
| @@ -143,8 +146,15 @@ extern void copy_page(void *to, void *from); | |||
| 143 | */ | 146 | */ |
| 144 | 147 | ||
| 145 | #if DCACHE_WAY_SIZE > PAGE_SIZE | 148 | #if DCACHE_WAY_SIZE > PAGE_SIZE |
| 146 | extern void clear_user_page(void*, unsigned long, struct page*); | 149 | extern void clear_page_alias(void *vaddr, unsigned long paddr); |
| 147 | extern void copy_user_page(void*, void*, unsigned long, struct page*); | 150 | extern void copy_page_alias(void *to, void *from, |
| 151 | unsigned long to_paddr, unsigned long from_paddr); | ||
| 152 | |||
| 153 | #define clear_user_highpage clear_user_highpage | ||
| 154 | void clear_user_highpage(struct page *page, unsigned long vaddr); | ||
| 155 | #define __HAVE_ARCH_COPY_USER_HIGHPAGE | ||
| 156 | void copy_user_highpage(struct page *to, struct page *from, | ||
| 157 | unsigned long vaddr, struct vm_area_struct *vma); | ||
| 148 | #else | 158 | #else |
| 149 | # define clear_user_page(page, vaddr, pg) clear_page(page) | 159 | # define clear_user_page(page, vaddr, pg) clear_page(page) |
| 150 | # define copy_user_page(to, from, vaddr, pg) copy_page(to, from) | 160 | # define copy_user_page(to, from, vaddr, pg) copy_page(to, from) |
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 4b0ca35a93b1..b2173e5da601 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h | |||
| @@ -67,7 +67,12 @@ | |||
| 67 | #define VMALLOC_START 0xC0000000 | 67 | #define VMALLOC_START 0xC0000000 |
| 68 | #define VMALLOC_END 0xC7FEFFFF | 68 | #define VMALLOC_END 0xC7FEFFFF |
| 69 | #define TLBTEMP_BASE_1 0xC7FF0000 | 69 | #define TLBTEMP_BASE_1 0xC7FF0000 |
| 70 | #define TLBTEMP_BASE_2 0xC7FF8000 | 70 | #define TLBTEMP_BASE_2 (TLBTEMP_BASE_1 + DCACHE_WAY_SIZE) |
| 71 | #if 2 * DCACHE_WAY_SIZE > ICACHE_WAY_SIZE | ||
| 72 | #define TLBTEMP_SIZE (2 * DCACHE_WAY_SIZE) | ||
| 73 | #else | ||
| 74 | #define TLBTEMP_SIZE ICACHE_WAY_SIZE | ||
| 75 | #endif | ||
| 71 | 76 | ||
| 72 | /* | 77 | /* |
| 73 | * For the Xtensa architecture, the PTE layout is as follows: | 78 | * For the Xtensa architecture, the PTE layout is as follows: |
diff --git a/arch/xtensa/include/asm/uaccess.h b/arch/xtensa/include/asm/uaccess.h index fd686dc45d1a..c7211e7e182d 100644 --- a/arch/xtensa/include/asm/uaccess.h +++ b/arch/xtensa/include/asm/uaccess.h | |||
| @@ -52,7 +52,12 @@ | |||
| 52 | */ | 52 | */ |
| 53 | .macro get_fs ad, sp | 53 | .macro get_fs ad, sp |
| 54 | GET_CURRENT(\ad,\sp) | 54 | GET_CURRENT(\ad,\sp) |
| 55 | #if THREAD_CURRENT_DS > 1020 | ||
| 56 | addi \ad, \ad, TASK_THREAD | ||
| 57 | l32i \ad, \ad, THREAD_CURRENT_DS - TASK_THREAD | ||
| 58 | #else | ||
| 55 | l32i \ad, \ad, THREAD_CURRENT_DS | 59 | l32i \ad, \ad, THREAD_CURRENT_DS |
| 60 | #endif | ||
| 56 | .endm | 61 | .endm |
| 57 | 62 | ||
| 58 | /* | 63 | /* |
diff --git a/arch/xtensa/include/uapi/asm/ioctls.h b/arch/xtensa/include/uapi/asm/ioctls.h index b4cb1100c0fb..a47909f0c34b 100644 --- a/arch/xtensa/include/uapi/asm/ioctls.h +++ b/arch/xtensa/include/uapi/asm/ioctls.h | |||
| @@ -28,17 +28,17 @@ | |||
| 28 | #define TCSETSW 0x5403 | 28 | #define TCSETSW 0x5403 |
| 29 | #define TCSETSF 0x5404 | 29 | #define TCSETSF 0x5404 |
| 30 | 30 | ||
| 31 | #define TCGETA _IOR('t', 23, struct termio) | 31 | #define TCGETA 0x80127417 /* _IOR('t', 23, struct termio) */ |
| 32 | #define TCSETA _IOW('t', 24, struct termio) | 32 | #define TCSETA 0x40127418 /* _IOW('t', 24, struct termio) */ |
| 33 | #define TCSETAW _IOW('t', 25, struct termio) | 33 | #define TCSETAW 0x40127419 /* _IOW('t', 25, struct termio) */ |
| 34 | #define TCSETAF _IOW('t', 28, struct termio) | 34 | #define TCSETAF 0x4012741C /* _IOW('t', 28, struct termio) */ |
| 35 | 35 | ||
| 36 | #define TCSBRK _IO('t', 29) | 36 | #define TCSBRK _IO('t', 29) |
| 37 | #define TCXONC _IO('t', 30) | 37 | #define TCXONC _IO('t', 30) |
| 38 | #define TCFLSH _IO('t', 31) | 38 | #define TCFLSH _IO('t', 31) |
| 39 | 39 | ||
| 40 | #define TIOCSWINSZ _IOW('t', 103, struct winsize) | 40 | #define TIOCSWINSZ 0x40087467 /* _IOW('t', 103, struct winsize) */ |
| 41 | #define TIOCGWINSZ _IOR('t', 104, struct winsize) | 41 | #define TIOCGWINSZ 0x80087468 /* _IOR('t', 104, struct winsize) */ |
| 42 | #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ | 42 | #define TIOCSTART _IO('t', 110) /* start output, like ^Q */ |
| 43 | #define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ | 43 | #define TIOCSTOP _IO('t', 111) /* stop output, like ^S */ |
| 44 | #define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ | 44 | #define TIOCOUTQ _IOR('t', 115, int) /* output queue size */ |
| @@ -88,7 +88,6 @@ | |||
| 88 | #define TIOCSETD _IOW('T', 35, int) | 88 | #define TIOCSETD _IOW('T', 35, int) |
| 89 | #define TIOCGETD _IOR('T', 36, int) | 89 | #define TIOCGETD _IOR('T', 36, int) |
| 90 | #define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/ | 90 | #define TCSBRKP _IOW('T', 37, int) /* Needed for POSIX tcsendbreak()*/ |
| 91 | #define TIOCTTYGSTRUCT _IOR('T', 38, struct tty_struct) /* For debugging only*/ | ||
| 92 | #define TIOCSBRK _IO('T', 39) /* BSD compatibility */ | 91 | #define TIOCSBRK _IO('T', 39) /* BSD compatibility */ |
| 93 | #define TIOCCBRK _IO('T', 40) /* BSD compatibility */ | 92 | #define TIOCCBRK _IO('T', 40) /* BSD compatibility */ |
| 94 | #define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/ | 93 | #define TIOCGSID _IOR('T', 41, pid_t) /* Return the session ID of FD*/ |
| @@ -114,8 +113,10 @@ | |||
| 114 | #define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */ | 113 | #define TIOCSERGETLSR _IOR('T', 89, unsigned int) /* Get line status reg. */ |
| 115 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ | 114 | /* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */ |
| 116 | # define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ | 115 | # define TIOCSER_TEMT 0x01 /* Transmitter physically empty */ |
| 117 | #define TIOCSERGETMULTI _IOR('T', 90, struct serial_multiport_struct) /* Get multiport config */ | 116 | #define TIOCSERGETMULTI 0x80a8545a /* Get multiport config */ |
| 118 | #define TIOCSERSETMULTI _IOW('T', 91, struct serial_multiport_struct) /* Set multiport config */ | 117 | /* _IOR('T', 90, struct serial_multiport_struct) */ |
| 118 | #define TIOCSERSETMULTI 0x40a8545b /* Set multiport config */ | ||
| 119 | /* _IOW('T', 91, struct serial_multiport_struct) */ | ||
| 119 | 120 | ||
| 120 | #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ | 121 | #define TIOCMIWAIT _IO('T', 92) /* wait for a change on serial input line(s) */ |
| 121 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ | 122 | #define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */ |
diff --git a/arch/xtensa/include/uapi/asm/unistd.h b/arch/xtensa/include/uapi/asm/unistd.h index b9395529f02d..8883fc877c5c 100644 --- a/arch/xtensa/include/uapi/asm/unistd.h +++ b/arch/xtensa/include/uapi/asm/unistd.h | |||
| @@ -739,7 +739,10 @@ __SYSCALL(334, sys_sched_setattr, 2) | |||
| 739 | #define __NR_sched_getattr 335 | 739 | #define __NR_sched_getattr 335 |
| 740 | __SYSCALL(335, sys_sched_getattr, 3) | 740 | __SYSCALL(335, sys_sched_getattr, 3) |
| 741 | 741 | ||
| 742 | #define __NR_syscall_count 336 | 742 | #define __NR_renameat2 336 |
| 743 | __SYSCALL(336, sys_renameat2, 5) | ||
| 744 | |||
| 745 | #define __NR_syscall_count 337 | ||
| 743 | 746 | ||
| 744 | /* | 747 | /* |
| 745 | * sysxtensa syscall handler | 748 | * sysxtensa syscall handler |
diff --git a/arch/xtensa/kernel/align.S b/arch/xtensa/kernel/align.S index d4cef6039a5c..890004af03a9 100644 --- a/arch/xtensa/kernel/align.S +++ b/arch/xtensa/kernel/align.S | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | * this archive for more details. | 8 | * this archive for more details. |
| 9 | * | 9 | * |
| 10 | * Copyright (C) 2001 - 2005 Tensilica, Inc. | 10 | * Copyright (C) 2001 - 2005 Tensilica, Inc. |
| 11 | * Copyright (C) 2014 Cadence Design Systems Inc. | ||
| 11 | * | 12 | * |
| 12 | * Rewritten by Chris Zankel <chris@zankel.net> | 13 | * Rewritten by Chris Zankel <chris@zankel.net> |
| 13 | * | 14 | * |
| @@ -174,6 +175,10 @@ ENTRY(fast_unaligned) | |||
| 174 | s32i a0, a2, PT_AREG2 | 175 | s32i a0, a2, PT_AREG2 |
| 175 | s32i a3, a2, PT_AREG3 | 176 | s32i a3, a2, PT_AREG3 |
| 176 | 177 | ||
| 178 | rsr a3, excsave1 | ||
| 179 | movi a4, fast_unaligned_fixup | ||
| 180 | s32i a4, a3, EXC_TABLE_FIXUP | ||
| 181 | |||
| 177 | /* Keep value of SAR in a0 */ | 182 | /* Keep value of SAR in a0 */ |
| 178 | 183 | ||
| 179 | rsr a0, sar | 184 | rsr a0, sar |
| @@ -225,10 +230,6 @@ ENTRY(fast_unaligned) | |||
| 225 | addx8 a5, a6, a5 | 230 | addx8 a5, a6, a5 |
| 226 | jx a5 # jump into table | 231 | jx a5 # jump into table |
| 227 | 232 | ||
| 228 | /* Invalid instruction, CRITICAL! */ | ||
| 229 | .Linvalid_instruction_load: | ||
| 230 | j .Linvalid_instruction | ||
| 231 | |||
| 232 | /* Load: Load memory address. */ | 233 | /* Load: Load memory address. */ |
| 233 | 234 | ||
| 234 | .Lload: movi a3, ~3 | 235 | .Lload: movi a3, ~3 |
| @@ -272,18 +273,6 @@ ENTRY(fast_unaligned) | |||
| 272 | /* Set target register. */ | 273 | /* Set target register. */ |
| 273 | 274 | ||
| 274 | 1: | 275 | 1: |
| 275 | |||
| 276 | #if XCHAL_HAVE_LOOPS | ||
| 277 | rsr a5, lend # check if we reached LEND | ||
| 278 | bne a7, a5, 1f | ||
| 279 | rsr a5, lcount # and LCOUNT != 0 | ||
| 280 | beqz a5, 1f | ||
| 281 | addi a5, a5, -1 # decrement LCOUNT and set | ||
| 282 | rsr a7, lbeg # set PC to LBEGIN | ||
| 283 | wsr a5, lcount | ||
| 284 | #endif | ||
| 285 | |||
| 286 | 1: wsr a7, epc1 # skip load instruction | ||
| 287 | extui a4, a4, INSN_T, 4 # extract target register | 276 | extui a4, a4, INSN_T, 4 # extract target register |
| 288 | movi a5, .Lload_table | 277 | movi a5, .Lload_table |
| 289 | addx8 a4, a4, a5 | 278 | addx8 a4, a4, a5 |
| @@ -326,6 +315,35 @@ ENTRY(fast_unaligned) | |||
| 326 | mov a3, a14 ; _j 1f; .align 8 | 315 | mov a3, a14 ; _j 1f; .align 8 |
| 327 | mov a3, a15 ; _j 1f; .align 8 | 316 | mov a3, a15 ; _j 1f; .align 8 |
| 328 | 317 | ||
| 318 | /* We cannot handle this exception. */ | ||
| 319 | |||
| 320 | .extern _kernel_exception | ||
| 321 | .Linvalid_instruction_load: | ||
| 322 | .Linvalid_instruction_store: | ||
| 323 | |||
| 324 | movi a4, 0 | ||
| 325 | rsr a3, excsave1 | ||
| 326 | s32i a4, a3, EXC_TABLE_FIXUP | ||
| 327 | |||
| 328 | /* Restore a4...a8 and SAR, set SP, and jump to default exception. */ | ||
| 329 | |||
| 330 | l32i a8, a2, PT_AREG8 | ||
| 331 | l32i a7, a2, PT_AREG7 | ||
| 332 | l32i a6, a2, PT_AREG6 | ||
| 333 | l32i a5, a2, PT_AREG5 | ||
| 334 | l32i a4, a2, PT_AREG4 | ||
| 335 | wsr a0, sar | ||
| 336 | mov a1, a2 | ||
| 337 | |||
| 338 | rsr a0, ps | ||
| 339 | bbsi.l a0, PS_UM_BIT, 2f # jump if user mode | ||
| 340 | |||
| 341 | movi a0, _kernel_exception | ||
| 342 | jx a0 | ||
| 343 | |||
| 344 | 2: movi a0, _user_exception | ||
| 345 | jx a0 | ||
| 346 | |||
| 329 | 1: # a7: instruction pointer, a4: instruction, a3: value | 347 | 1: # a7: instruction pointer, a4: instruction, a3: value |
| 330 | 348 | ||
| 331 | movi a6, 0 # mask: ffffffff:00000000 | 349 | movi a6, 0 # mask: ffffffff:00000000 |
| @@ -353,17 +371,6 @@ ENTRY(fast_unaligned) | |||
| 353 | /* Get memory address */ | 371 | /* Get memory address */ |
| 354 | 372 | ||
| 355 | 1: | 373 | 1: |
| 356 | #if XCHAL_HAVE_LOOPS | ||
| 357 | rsr a4, lend # check if we reached LEND | ||
| 358 | bne a7, a4, 1f | ||
| 359 | rsr a4, lcount # and LCOUNT != 0 | ||
| 360 | beqz a4, 1f | ||
| 361 | addi a4, a4, -1 # decrement LCOUNT and set | ||
| 362 | rsr a7, lbeg # set PC to LBEGIN | ||
| 363 | wsr a4, lcount | ||
| 364 | #endif | ||
| 365 | |||
| 366 | 1: wsr a7, epc1 # skip store instruction | ||
| 367 | movi a4, ~3 | 374 | movi a4, ~3 |
| 368 | and a4, a4, a8 # align memory address | 375 | and a4, a4, a8 # align memory address |
| 369 | 376 | ||
| @@ -375,25 +382,25 @@ ENTRY(fast_unaligned) | |||
| 375 | #endif | 382 | #endif |
| 376 | 383 | ||
| 377 | __ssa8r a8 | 384 | __ssa8r a8 |
| 378 | __src_b a7, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE) | 385 | __src_b a8, a5, a6 # lo-mask F..F0..0 (BE) 0..0F..F (LE) |
| 379 | __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE) | 386 | __src_b a6, a6, a5 # hi-mask 0..0F..F (BE) F..F0..0 (LE) |
| 380 | #ifdef UNALIGNED_USER_EXCEPTION | 387 | #ifdef UNALIGNED_USER_EXCEPTION |
| 381 | l32e a5, a4, -8 | 388 | l32e a5, a4, -8 |
| 382 | #else | 389 | #else |
| 383 | l32i a5, a4, 0 # load lower address word | 390 | l32i a5, a4, 0 # load lower address word |
| 384 | #endif | 391 | #endif |
| 385 | and a5, a5, a7 # mask | 392 | and a5, a5, a8 # mask |
| 386 | __sh a7, a3 # shift value | 393 | __sh a8, a3 # shift value |
| 387 | or a5, a5, a7 # or with original value | 394 | or a5, a5, a8 # or with original value |
| 388 | #ifdef UNALIGNED_USER_EXCEPTION | 395 | #ifdef UNALIGNED_USER_EXCEPTION |
| 389 | s32e a5, a4, -8 | 396 | s32e a5, a4, -8 |
| 390 | l32e a7, a4, -4 | 397 | l32e a8, a4, -4 |
| 391 | #else | 398 | #else |
| 392 | s32i a5, a4, 0 # store | 399 | s32i a5, a4, 0 # store |
| 393 | l32i a7, a4, 4 # same for upper address word | 400 | l32i a8, a4, 4 # same for upper address word |
| 394 | #endif | 401 | #endif |
| 395 | __sl a5, a3 | 402 | __sl a5, a3 |
| 396 | and a6, a7, a6 | 403 | and a6, a8, a6 |
| 397 | or a6, a6, a5 | 404 | or a6, a6, a5 |
| 398 | #ifdef UNALIGNED_USER_EXCEPTION | 405 | #ifdef UNALIGNED_USER_EXCEPTION |
| 399 | s32e a6, a4, -4 | 406 | s32e a6, a4, -4 |
| @@ -401,9 +408,27 @@ ENTRY(fast_unaligned) | |||
| 401 | s32i a6, a4, 4 | 408 | s32i a6, a4, 4 |
| 402 | #endif | 409 | #endif |
| 403 | 410 | ||
| 404 | /* Done. restore stack and return */ | ||
| 405 | |||
| 406 | .Lexit: | 411 | .Lexit: |
| 412 | #if XCHAL_HAVE_LOOPS | ||
| 413 | rsr a4, lend # check if we reached LEND | ||
| 414 | bne a7, a4, 1f | ||
| 415 | rsr a4, lcount # and LCOUNT != 0 | ||
| 416 | beqz a4, 1f | ||
| 417 | addi a4, a4, -1 # decrement LCOUNT and set | ||
| 418 | rsr a7, lbeg # set PC to LBEGIN | ||
| 419 | wsr a4, lcount | ||
| 420 | #endif | ||
| 421 | |||
| 422 | 1: wsr a7, epc1 # skip emulated instruction | ||
| 423 | |||
| 424 | /* Update icount if we're single-stepping in userspace. */ | ||
| 425 | rsr a4, icountlevel | ||
| 426 | beqz a4, 1f | ||
| 427 | bgeui a4, LOCKLEVEL + 1, 1f | ||
| 428 | rsr a4, icount | ||
| 429 | addi a4, a4, 1 | ||
| 430 | wsr a4, icount | ||
| 431 | 1: | ||
| 407 | movi a4, 0 | 432 | movi a4, 0 |
| 408 | rsr a3, excsave1 | 433 | rsr a3, excsave1 |
| 409 | s32i a4, a3, EXC_TABLE_FIXUP | 434 | s32i a4, a3, EXC_TABLE_FIXUP |
| @@ -424,31 +449,40 @@ ENTRY(fast_unaligned) | |||
| 424 | l32i a2, a2, PT_AREG2 | 449 | l32i a2, a2, PT_AREG2 |
| 425 | rfe | 450 | rfe |
| 426 | 451 | ||
| 427 | /* We cannot handle this exception. */ | 452 | ENDPROC(fast_unaligned) |
| 428 | 453 | ||
| 429 | .extern _kernel_exception | 454 | ENTRY(fast_unaligned_fixup) |
| 430 | .Linvalid_instruction_store: | ||
| 431 | .Linvalid_instruction: | ||
| 432 | 455 | ||
| 433 | /* Restore a4...a8 and SAR, set SP, and jump to default exception. */ | 456 | l32i a2, a3, EXC_TABLE_DOUBLE_SAVE |
| 457 | wsr a3, excsave1 | ||
| 434 | 458 | ||
| 435 | l32i a8, a2, PT_AREG8 | 459 | l32i a8, a2, PT_AREG8 |
| 436 | l32i a7, a2, PT_AREG7 | 460 | l32i a7, a2, PT_AREG7 |
| 437 | l32i a6, a2, PT_AREG6 | 461 | l32i a6, a2, PT_AREG6 |
| 438 | l32i a5, a2, PT_AREG5 | 462 | l32i a5, a2, PT_AREG5 |
| 439 | l32i a4, a2, PT_AREG4 | 463 | l32i a4, a2, PT_AREG4 |
| 464 | l32i a0, a2, PT_AREG2 | ||
| 465 | xsr a0, depc # restore depc and a0 | ||
| 440 | wsr a0, sar | 466 | wsr a0, sar |
| 441 | mov a1, a2 | 467 | |
| 468 | rsr a0, exccause | ||
| 469 | s32i a0, a2, PT_DEPC # mark as a regular exception | ||
| 442 | 470 | ||
| 443 | rsr a0, ps | 471 | rsr a0, ps |
| 444 | bbsi.l a2, PS_UM_BIT, 1f # jump if user mode | 472 | bbsi.l a0, PS_UM_BIT, 1f # jump if user mode |
| 445 | 473 | ||
| 446 | movi a0, _kernel_exception | 474 | rsr a0, exccause |
| 475 | addx4 a0, a0, a3 # find entry in table | ||
| 476 | l32i a0, a0, EXC_TABLE_FAST_KERNEL # load handler | ||
| 477 | l32i a3, a2, PT_AREG3 | ||
| 447 | jx a0 | 478 | jx a0 |
| 448 | 479 | 1: | |
| 449 | 1: movi a0, _user_exception | 480 | rsr a0, exccause |
| 481 | addx4 a0, a0, a3 # find entry in table | ||
| 482 | l32i a0, a0, EXC_TABLE_FAST_USER # load handler | ||
| 483 | l32i a3, a2, PT_AREG3 | ||
| 450 | jx a0 | 484 | jx a0 |
| 451 | 485 | ||
| 452 | ENDPROC(fast_unaligned) | 486 | ENDPROC(fast_unaligned_fixup) |
| 453 | 487 | ||
| 454 | #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ | 488 | #endif /* XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION */ |
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index ef7f4990722b..82bbfa5a05b3 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
| @@ -986,6 +986,8 @@ ENDPROC(fast_syscall_unrecoverable) | |||
| 986 | * j done | 986 | * j done |
| 987 | */ | 987 | */ |
| 988 | 988 | ||
| 989 | #ifdef CONFIG_FAST_SYSCALL_XTENSA | ||
| 990 | |||
| 989 | #define TRY \ | 991 | #define TRY \ |
| 990 | .section __ex_table, "a"; \ | 992 | .section __ex_table, "a"; \ |
| 991 | .word 66f, 67f; \ | 993 | .word 66f, 67f; \ |
| @@ -1001,9 +1003,8 @@ ENTRY(fast_syscall_xtensa) | |||
| 1001 | movi a7, 4 # sizeof(unsigned int) | 1003 | movi a7, 4 # sizeof(unsigned int) |
| 1002 | access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp | 1004 | access_ok a3, a7, a0, a2, .Leac # a0: scratch reg, a2: sp |
| 1003 | 1005 | ||
| 1004 | addi a6, a6, -1 # assuming SYS_XTENSA_ATOMIC_SET = 1 | 1006 | _bgeui a6, SYS_XTENSA_COUNT, .Lill |
| 1005 | _bgeui a6, SYS_XTENSA_COUNT - 1, .Lill | 1007 | _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP, .Lnswp |
| 1006 | _bnei a6, SYS_XTENSA_ATOMIC_CMP_SWP - 1, .Lnswp | ||
| 1007 | 1008 | ||
| 1008 | /* Fall through for ATOMIC_CMP_SWP. */ | 1009 | /* Fall through for ATOMIC_CMP_SWP. */ |
| 1009 | 1010 | ||
| @@ -1015,27 +1016,26 @@ TRY s32i a5, a3, 0 # different, modify value | |||
| 1015 | l32i a7, a2, PT_AREG7 # restore a7 | 1016 | l32i a7, a2, PT_AREG7 # restore a7 |
| 1016 | l32i a0, a2, PT_AREG0 # restore a0 | 1017 | l32i a0, a2, PT_AREG0 # restore a0 |
| 1017 | movi a2, 1 # and return 1 | 1018 | movi a2, 1 # and return 1 |
| 1018 | addi a6, a6, 1 # restore a6 (really necessary?) | ||
| 1019 | rfe | 1019 | rfe |
| 1020 | 1020 | ||
| 1021 | 1: l32i a7, a2, PT_AREG7 # restore a7 | 1021 | 1: l32i a7, a2, PT_AREG7 # restore a7 |
| 1022 | l32i a0, a2, PT_AREG0 # restore a0 | 1022 | l32i a0, a2, PT_AREG0 # restore a0 |
| 1023 | movi a2, 0 # return 0 (note that we cannot set | 1023 | movi a2, 0 # return 0 (note that we cannot set |
| 1024 | addi a6, a6, 1 # restore a6 (really necessary?) | ||
| 1025 | rfe | 1024 | rfe |
| 1026 | 1025 | ||
| 1027 | .Lnswp: /* Atomic set, add, and exg_add. */ | 1026 | .Lnswp: /* Atomic set, add, and exg_add. */ |
| 1028 | 1027 | ||
| 1029 | TRY l32i a7, a3, 0 # orig | 1028 | TRY l32i a7, a3, 0 # orig |
| 1029 | addi a6, a6, -SYS_XTENSA_ATOMIC_SET | ||
| 1030 | add a0, a4, a7 # + arg | 1030 | add a0, a4, a7 # + arg |
| 1031 | moveqz a0, a4, a6 # set | 1031 | moveqz a0, a4, a6 # set |
| 1032 | addi a6, a6, SYS_XTENSA_ATOMIC_SET | ||
| 1032 | TRY s32i a0, a3, 0 # write new value | 1033 | TRY s32i a0, a3, 0 # write new value |
| 1033 | 1034 | ||
| 1034 | mov a0, a2 | 1035 | mov a0, a2 |
| 1035 | mov a2, a7 | 1036 | mov a2, a7 |
| 1036 | l32i a7, a0, PT_AREG7 # restore a7 | 1037 | l32i a7, a0, PT_AREG7 # restore a7 |
| 1037 | l32i a0, a0, PT_AREG0 # restore a0 | 1038 | l32i a0, a0, PT_AREG0 # restore a0 |
| 1038 | addi a6, a6, 1 # restore a6 (really necessary?) | ||
| 1039 | rfe | 1039 | rfe |
| 1040 | 1040 | ||
| 1041 | CATCH | 1041 | CATCH |
| @@ -1044,13 +1044,25 @@ CATCH | |||
| 1044 | movi a2, -EFAULT | 1044 | movi a2, -EFAULT |
| 1045 | rfe | 1045 | rfe |
| 1046 | 1046 | ||
| 1047 | .Lill: l32i a7, a2, PT_AREG0 # restore a7 | 1047 | .Lill: l32i a7, a2, PT_AREG7 # restore a7 |
| 1048 | l32i a0, a2, PT_AREG0 # restore a0 | 1048 | l32i a0, a2, PT_AREG0 # restore a0 |
| 1049 | movi a2, -EINVAL | 1049 | movi a2, -EINVAL |
| 1050 | rfe | 1050 | rfe |
| 1051 | 1051 | ||
| 1052 | ENDPROC(fast_syscall_xtensa) | 1052 | ENDPROC(fast_syscall_xtensa) |
| 1053 | 1053 | ||
| 1054 | #else /* CONFIG_FAST_SYSCALL_XTENSA */ | ||
| 1055 | |||
| 1056 | ENTRY(fast_syscall_xtensa) | ||
| 1057 | |||
| 1058 | l32i a0, a2, PT_AREG0 # restore a0 | ||
| 1059 | movi a2, -ENOSYS | ||
| 1060 | rfe | ||
| 1061 | |||
| 1062 | ENDPROC(fast_syscall_xtensa) | ||
| 1063 | |||
| 1064 | #endif /* CONFIG_FAST_SYSCALL_XTENSA */ | ||
| 1065 | |||
| 1054 | 1066 | ||
| 1055 | /* fast_syscall_spill_registers. | 1067 | /* fast_syscall_spill_registers. |
| 1056 | * | 1068 | * |
| @@ -1066,6 +1078,8 @@ ENDPROC(fast_syscall_xtensa) | |||
| 1066 | * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. | 1078 | * Note: We assume the stack pointer is EXC_TABLE_KSTK in the fixup handler. |
| 1067 | */ | 1079 | */ |
| 1068 | 1080 | ||
| 1081 | #ifdef CONFIG_FAST_SYSCALL_SPILL_REGISTERS | ||
| 1082 | |||
| 1069 | ENTRY(fast_syscall_spill_registers) | 1083 | ENTRY(fast_syscall_spill_registers) |
| 1070 | 1084 | ||
| 1071 | /* Register a FIXUP handler (pass current wb as a parameter) */ | 1085 | /* Register a FIXUP handler (pass current wb as a parameter) */ |
| @@ -1400,6 +1414,18 @@ ENTRY(fast_syscall_spill_registers_fixup_return) | |||
| 1400 | 1414 | ||
| 1401 | ENDPROC(fast_syscall_spill_registers_fixup_return) | 1415 | ENDPROC(fast_syscall_spill_registers_fixup_return) |
| 1402 | 1416 | ||
| 1417 | #else /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */ | ||
| 1418 | |||
| 1419 | ENTRY(fast_syscall_spill_registers) | ||
| 1420 | |||
| 1421 | l32i a0, a2, PT_AREG0 # restore a0 | ||
| 1422 | movi a2, -ENOSYS | ||
| 1423 | rfe | ||
| 1424 | |||
| 1425 | ENDPROC(fast_syscall_spill_registers) | ||
| 1426 | |||
| 1427 | #endif /* CONFIG_FAST_SYSCALL_SPILL_REGISTERS */ | ||
| 1428 | |||
| 1403 | #ifdef CONFIG_MMU | 1429 | #ifdef CONFIG_MMU |
| 1404 | /* | 1430 | /* |
| 1405 | * We should never get here. Bail out! | 1431 | * We should never get here. Bail out! |
| @@ -1565,7 +1591,7 @@ ENTRY(fast_second_level_miss) | |||
| 1565 | rsr a0, excvaddr | 1591 | rsr a0, excvaddr |
| 1566 | bltu a0, a3, 2f | 1592 | bltu a0, a3, 2f |
| 1567 | 1593 | ||
| 1568 | addi a1, a0, -(2 << (DCACHE_ALIAS_ORDER + PAGE_SHIFT)) | 1594 | addi a1, a0, -TLBTEMP_SIZE |
| 1569 | bgeu a1, a3, 2f | 1595 | bgeu a1, a3, 2f |
| 1570 | 1596 | ||
| 1571 | /* Check if we have to restore an ITLB mapping. */ | 1597 | /* Check if we have to restore an ITLB mapping. */ |
| @@ -1820,7 +1846,6 @@ ENTRY(_switch_to) | |||
| 1820 | 1846 | ||
| 1821 | entry a1, 16 | 1847 | entry a1, 16 |
| 1822 | 1848 | ||
| 1823 | mov a10, a2 # preserve 'prev' (a2) | ||
| 1824 | mov a11, a3 # and 'next' (a3) | 1849 | mov a11, a3 # and 'next' (a3) |
| 1825 | 1850 | ||
| 1826 | l32i a4, a2, TASK_THREAD_INFO | 1851 | l32i a4, a2, TASK_THREAD_INFO |
| @@ -1828,8 +1853,14 @@ ENTRY(_switch_to) | |||
| 1828 | 1853 | ||
| 1829 | save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER | 1854 | save_xtregs_user a4 a6 a8 a9 a12 a13 THREAD_XTREGS_USER |
| 1830 | 1855 | ||
| 1831 | s32i a0, a10, THREAD_RA # save return address | 1856 | #if THREAD_RA > 1020 || THREAD_SP > 1020 |
| 1832 | s32i a1, a10, THREAD_SP # save stack pointer | 1857 | addi a10, a2, TASK_THREAD |
| 1858 | s32i a0, a10, THREAD_RA - TASK_THREAD # save return address | ||
| 1859 | s32i a1, a10, THREAD_SP - TASK_THREAD # save stack pointer | ||
| 1860 | #else | ||
| 1861 | s32i a0, a2, THREAD_RA # save return address | ||
| 1862 | s32i a1, a2, THREAD_SP # save stack pointer | ||
| 1863 | #endif | ||
| 1833 | 1864 | ||
| 1834 | /* Disable ints while we manipulate the stack pointer. */ | 1865 | /* Disable ints while we manipulate the stack pointer. */ |
| 1835 | 1866 | ||
| @@ -1870,7 +1901,6 @@ ENTRY(_switch_to) | |||
| 1870 | load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER | 1901 | load_xtregs_user a5 a6 a8 a9 a12 a13 THREAD_XTREGS_USER |
| 1871 | 1902 | ||
| 1872 | wsr a14, ps | 1903 | wsr a14, ps |
| 1873 | mov a2, a10 # return 'prev' | ||
| 1874 | rsync | 1904 | rsync |
| 1875 | 1905 | ||
| 1876 | retw | 1906 | retw |
diff --git a/arch/xtensa/kernel/pci-dma.c b/arch/xtensa/kernel/pci-dma.c index 2d9cc6dbfd78..e8b76b8e4b29 100644 --- a/arch/xtensa/kernel/pci-dma.c +++ b/arch/xtensa/kernel/pci-dma.c | |||
| @@ -49,9 +49,8 @@ dma_alloc_coherent(struct device *dev,size_t size,dma_addr_t *handle,gfp_t flag) | |||
| 49 | 49 | ||
| 50 | /* We currently don't support coherent memory outside KSEG */ | 50 | /* We currently don't support coherent memory outside KSEG */ |
| 51 | 51 | ||
| 52 | if (ret < XCHAL_KSEG_CACHED_VADDR | 52 | BUG_ON(ret < XCHAL_KSEG_CACHED_VADDR || |
| 53 | || ret >= XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE) | 53 | ret > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); |
| 54 | BUG(); | ||
| 55 | 54 | ||
| 56 | 55 | ||
| 57 | if (ret != 0) { | 56 | if (ret != 0) { |
| @@ -68,10 +67,11 @@ EXPORT_SYMBOL(dma_alloc_coherent); | |||
| 68 | void dma_free_coherent(struct device *hwdev, size_t size, | 67 | void dma_free_coherent(struct device *hwdev, size_t size, |
| 69 | void *vaddr, dma_addr_t dma_handle) | 68 | void *vaddr, dma_addr_t dma_handle) |
| 70 | { | 69 | { |
| 71 | long addr=(long)vaddr+XCHAL_KSEG_CACHED_VADDR-XCHAL_KSEG_BYPASS_VADDR; | 70 | unsigned long addr = (unsigned long)vaddr + |
| 71 | XCHAL_KSEG_CACHED_VADDR - XCHAL_KSEG_BYPASS_VADDR; | ||
| 72 | 72 | ||
| 73 | if (addr < 0 || addr >= XCHAL_KSEG_SIZE) | 73 | BUG_ON(addr < XCHAL_KSEG_CACHED_VADDR || |
| 74 | BUG(); | 74 | addr > XCHAL_KSEG_CACHED_VADDR + XCHAL_KSEG_SIZE - 1); |
| 75 | 75 | ||
| 76 | free_pages(addr, get_order(size)); | 76 | free_pages(addr, get_order(size)); |
| 77 | } | 77 | } |
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index eebbfd8c26fc..9d2f45f010ef 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c | |||
| @@ -101,9 +101,8 @@ static dispatch_init_table_t __initdata dispatch_init_table[] = { | |||
| 101 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION | 101 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION |
| 102 | #ifdef CONFIG_XTENSA_UNALIGNED_USER | 102 | #ifdef CONFIG_XTENSA_UNALIGNED_USER |
| 103 | { EXCCAUSE_UNALIGNED, USER, fast_unaligned }, | 103 | { EXCCAUSE_UNALIGNED, USER, fast_unaligned }, |
| 104 | #else | ||
| 105 | { EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, | ||
| 106 | #endif | 104 | #endif |
| 105 | { EXCCAUSE_UNALIGNED, 0, do_unaligned_user }, | ||
| 107 | { EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, | 106 | { EXCCAUSE_UNALIGNED, KRNL, fast_unaligned }, |
| 108 | #endif | 107 | #endif |
| 109 | #ifdef CONFIG_MMU | 108 | #ifdef CONFIG_MMU |
| @@ -264,7 +263,6 @@ do_illegal_instruction(struct pt_regs *regs) | |||
| 264 | */ | 263 | */ |
| 265 | 264 | ||
| 266 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION | 265 | #if XCHAL_UNALIGNED_LOAD_EXCEPTION || XCHAL_UNALIGNED_STORE_EXCEPTION |
| 267 | #ifndef CONFIG_XTENSA_UNALIGNED_USER | ||
| 268 | void | 266 | void |
| 269 | do_unaligned_user (struct pt_regs *regs) | 267 | do_unaligned_user (struct pt_regs *regs) |
| 270 | { | 268 | { |
| @@ -286,7 +284,6 @@ do_unaligned_user (struct pt_regs *regs) | |||
| 286 | 284 | ||
| 287 | } | 285 | } |
| 288 | #endif | 286 | #endif |
| 289 | #endif | ||
| 290 | 287 | ||
| 291 | void | 288 | void |
| 292 | do_debug(struct pt_regs *regs) | 289 | do_debug(struct pt_regs *regs) |
diff --git a/arch/xtensa/kernel/vectors.S b/arch/xtensa/kernel/vectors.S index 8453e6e39895..1b397a902292 100644 --- a/arch/xtensa/kernel/vectors.S +++ b/arch/xtensa/kernel/vectors.S | |||
| @@ -454,8 +454,14 @@ _DoubleExceptionVector_WindowOverflow: | |||
| 454 | s32i a0, a2, PT_DEPC | 454 | s32i a0, a2, PT_DEPC |
| 455 | 455 | ||
| 456 | _DoubleExceptionVector_handle_exception: | 456 | _DoubleExceptionVector_handle_exception: |
| 457 | addi a0, a0, -EXCCAUSE_UNALIGNED | ||
| 458 | beqz a0, 2f | ||
| 457 | addx4 a0, a0, a3 | 459 | addx4 a0, a0, a3 |
| 458 | l32i a0, a0, EXC_TABLE_FAST_USER | 460 | l32i a0, a0, EXC_TABLE_FAST_USER + 4 * EXCCAUSE_UNALIGNED |
| 461 | xsr a3, excsave1 | ||
| 462 | jx a0 | ||
| 463 | 2: | ||
| 464 | movi a0, user_exception | ||
| 459 | xsr a3, excsave1 | 465 | xsr a3, excsave1 |
| 460 | jx a0 | 466 | jx a0 |
| 461 | 467 | ||
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index d16db6df86f8..fc1bc2ba8d5d 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S | |||
| @@ -269,13 +269,13 @@ SECTIONS | |||
| 269 | .UserExceptionVector.literal) | 269 | .UserExceptionVector.literal) |
| 270 | SECTION_VECTOR (_DoubleExceptionVector_literal, | 270 | SECTION_VECTOR (_DoubleExceptionVector_literal, |
| 271 | .DoubleExceptionVector.literal, | 271 | .DoubleExceptionVector.literal, |
| 272 | DOUBLEEXC_VECTOR_VADDR - 40, | 272 | DOUBLEEXC_VECTOR_VADDR - 48, |
| 273 | SIZEOF(.UserExceptionVector.text), | 273 | SIZEOF(.UserExceptionVector.text), |
| 274 | .UserExceptionVector.text) | 274 | .UserExceptionVector.text) |
| 275 | SECTION_VECTOR (_DoubleExceptionVector_text, | 275 | SECTION_VECTOR (_DoubleExceptionVector_text, |
| 276 | .DoubleExceptionVector.text, | 276 | .DoubleExceptionVector.text, |
| 277 | DOUBLEEXC_VECTOR_VADDR, | 277 | DOUBLEEXC_VECTOR_VADDR, |
| 278 | 40, | 278 | 48, |
| 279 | .DoubleExceptionVector.literal) | 279 | .DoubleExceptionVector.literal) |
| 280 | 280 | ||
| 281 | . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; | 281 | . = (LOADADDR( .DoubleExceptionVector.text ) + SIZEOF( .DoubleExceptionVector.text ) + 3) & ~ 3; |
diff --git a/arch/xtensa/mm/cache.c b/arch/xtensa/mm/cache.c index 63cbb867dadd..d75aa1476da7 100644 --- a/arch/xtensa/mm/cache.c +++ b/arch/xtensa/mm/cache.c | |||
| @@ -59,9 +59,68 @@ | |||
| 59 | * | 59 | * |
| 60 | */ | 60 | */ |
| 61 | 61 | ||
| 62 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && defined(CONFIG_HIGHMEM) | 62 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) |
| 63 | #error "HIGHMEM is not supported on cores with aliasing cache." | 63 | static inline void kmap_invalidate_coherent(struct page *page, |
| 64 | #endif | 64 | unsigned long vaddr) |
| 65 | { | ||
| 66 | if (!DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { | ||
| 67 | unsigned long kvaddr; | ||
| 68 | |||
| 69 | if (!PageHighMem(page)) { | ||
| 70 | kvaddr = (unsigned long)page_to_virt(page); | ||
| 71 | |||
| 72 | __invalidate_dcache_page(kvaddr); | ||
| 73 | } else { | ||
| 74 | kvaddr = TLBTEMP_BASE_1 + | ||
| 75 | (page_to_phys(page) & DCACHE_ALIAS_MASK); | ||
| 76 | |||
| 77 | __invalidate_dcache_page_alias(kvaddr, | ||
| 78 | page_to_phys(page)); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | } | ||
| 82 | |||
| 83 | static inline void *coherent_kvaddr(struct page *page, unsigned long base, | ||
| 84 | unsigned long vaddr, unsigned long *paddr) | ||
| 85 | { | ||
| 86 | if (PageHighMem(page) || !DCACHE_ALIAS_EQ(page_to_phys(page), vaddr)) { | ||
| 87 | *paddr = page_to_phys(page); | ||
| 88 | return (void *)(base + (vaddr & DCACHE_ALIAS_MASK)); | ||
| 89 | } else { | ||
| 90 | *paddr = 0; | ||
| 91 | return page_to_virt(page); | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | void clear_user_highpage(struct page *page, unsigned long vaddr) | ||
| 96 | { | ||
| 97 | unsigned long paddr; | ||
| 98 | void *kvaddr = coherent_kvaddr(page, TLBTEMP_BASE_1, vaddr, &paddr); | ||
| 99 | |||
| 100 | pagefault_disable(); | ||
| 101 | kmap_invalidate_coherent(page, vaddr); | ||
| 102 | set_bit(PG_arch_1, &page->flags); | ||
| 103 | clear_page_alias(kvaddr, paddr); | ||
| 104 | pagefault_enable(); | ||
| 105 | } | ||
| 106 | |||
| 107 | void copy_user_highpage(struct page *dst, struct page *src, | ||
| 108 | unsigned long vaddr, struct vm_area_struct *vma) | ||
| 109 | { | ||
| 110 | unsigned long dst_paddr, src_paddr; | ||
| 111 | void *dst_vaddr = coherent_kvaddr(dst, TLBTEMP_BASE_1, vaddr, | ||
| 112 | &dst_paddr); | ||
| 113 | void *src_vaddr = coherent_kvaddr(src, TLBTEMP_BASE_2, vaddr, | ||
| 114 | &src_paddr); | ||
| 115 | |||
| 116 | pagefault_disable(); | ||
| 117 | kmap_invalidate_coherent(dst, vaddr); | ||
| 118 | set_bit(PG_arch_1, &dst->flags); | ||
| 119 | copy_page_alias(dst_vaddr, src_vaddr, dst_paddr, src_paddr); | ||
| 120 | pagefault_enable(); | ||
| 121 | } | ||
| 122 | |||
| 123 | #endif /* DCACHE_WAY_SIZE > PAGE_SIZE */ | ||
| 65 | 124 | ||
| 66 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK | 125 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK |
| 67 | 126 | ||
| @@ -103,7 +162,8 @@ void flush_dcache_page(struct page *page) | |||
| 103 | if (!alias && !mapping) | 162 | if (!alias && !mapping) |
| 104 | return; | 163 | return; |
| 105 | 164 | ||
| 106 | __flush_invalidate_dcache_page((long)page_address(page)); | 165 | virt = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); |
| 166 | __flush_invalidate_dcache_page_alias(virt, phys); | ||
| 107 | 167 | ||
| 108 | virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK); | 168 | virt = TLBTEMP_BASE_1 + (temp & DCACHE_ALIAS_MASK); |
| 109 | 169 | ||
| @@ -168,13 +228,12 @@ update_mmu_cache(struct vm_area_struct * vma, unsigned long addr, pte_t *ptep) | |||
| 168 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK | 228 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) && XCHAL_DCACHE_IS_WRITEBACK |
| 169 | 229 | ||
| 170 | if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) { | 230 | if (!PageReserved(page) && test_bit(PG_arch_1, &page->flags)) { |
| 171 | |||
| 172 | unsigned long paddr = (unsigned long) page_address(page); | ||
| 173 | unsigned long phys = page_to_phys(page); | 231 | unsigned long phys = page_to_phys(page); |
| 174 | unsigned long tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); | 232 | unsigned long tmp; |
| 175 | |||
| 176 | __flush_invalidate_dcache_page(paddr); | ||
| 177 | 233 | ||
| 234 | tmp = TLBTEMP_BASE_1 + (phys & DCACHE_ALIAS_MASK); | ||
| 235 | __flush_invalidate_dcache_page_alias(tmp, phys); | ||
| 236 | tmp = TLBTEMP_BASE_1 + (addr & DCACHE_ALIAS_MASK); | ||
| 178 | __flush_invalidate_dcache_page_alias(tmp, phys); | 237 | __flush_invalidate_dcache_page_alias(tmp, phys); |
| 179 | __invalidate_icache_page_alias(tmp, phys); | 238 | __invalidate_icache_page_alias(tmp, phys); |
| 180 | 239 | ||
diff --git a/arch/xtensa/mm/highmem.c b/arch/xtensa/mm/highmem.c index 17a8c0d6fd17..8cfb71ec0937 100644 --- a/arch/xtensa/mm/highmem.c +++ b/arch/xtensa/mm/highmem.c | |||
| @@ -14,23 +14,45 @@ | |||
| 14 | 14 | ||
| 15 | static pte_t *kmap_pte; | 15 | static pte_t *kmap_pte; |
| 16 | 16 | ||
| 17 | #if DCACHE_WAY_SIZE > PAGE_SIZE | ||
| 18 | unsigned int last_pkmap_nr_arr[DCACHE_N_COLORS]; | ||
| 19 | wait_queue_head_t pkmap_map_wait_arr[DCACHE_N_COLORS]; | ||
| 20 | |||
| 21 | static void __init kmap_waitqueues_init(void) | ||
| 22 | { | ||
| 23 | unsigned int i; | ||
| 24 | |||
| 25 | for (i = 0; i < ARRAY_SIZE(pkmap_map_wait_arr); ++i) | ||
| 26 | init_waitqueue_head(pkmap_map_wait_arr + i); | ||
| 27 | } | ||
| 28 | #else | ||
| 29 | static inline void kmap_waitqueues_init(void) | ||
| 30 | { | ||
| 31 | } | ||
| 32 | #endif | ||
| 33 | |||
| 34 | static inline enum fixed_addresses kmap_idx(int type, unsigned long color) | ||
| 35 | { | ||
| 36 | return (type + KM_TYPE_NR * smp_processor_id()) * DCACHE_N_COLORS + | ||
| 37 | color; | ||
| 38 | } | ||
| 39 | |||
| 17 | void *kmap_atomic(struct page *page) | 40 | void *kmap_atomic(struct page *page) |
| 18 | { | 41 | { |
| 19 | enum fixed_addresses idx; | 42 | enum fixed_addresses idx; |
| 20 | unsigned long vaddr; | 43 | unsigned long vaddr; |
| 21 | int type; | ||
| 22 | 44 | ||
| 23 | pagefault_disable(); | 45 | pagefault_disable(); |
| 24 | if (!PageHighMem(page)) | 46 | if (!PageHighMem(page)) |
| 25 | return page_address(page); | 47 | return page_address(page); |
| 26 | 48 | ||
| 27 | type = kmap_atomic_idx_push(); | 49 | idx = kmap_idx(kmap_atomic_idx_push(), |
| 28 | idx = type + KM_TYPE_NR * smp_processor_id(); | 50 | DCACHE_ALIAS(page_to_phys(page))); |
| 29 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); | 51 | vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
| 30 | #ifdef CONFIG_DEBUG_HIGHMEM | 52 | #ifdef CONFIG_DEBUG_HIGHMEM |
| 31 | BUG_ON(!pte_none(*(kmap_pte - idx))); | 53 | BUG_ON(!pte_none(*(kmap_pte + idx))); |
| 32 | #endif | 54 | #endif |
| 33 | set_pte(kmap_pte - idx, mk_pte(page, PAGE_KERNEL_EXEC)); | 55 | set_pte(kmap_pte + idx, mk_pte(page, PAGE_KERNEL_EXEC)); |
| 34 | 56 | ||
| 35 | return (void *)vaddr; | 57 | return (void *)vaddr; |
| 36 | } | 58 | } |
| @@ -38,12 +60,10 @@ EXPORT_SYMBOL(kmap_atomic); | |||
| 38 | 60 | ||
| 39 | void __kunmap_atomic(void *kvaddr) | 61 | void __kunmap_atomic(void *kvaddr) |
| 40 | { | 62 | { |
| 41 | int idx, type; | ||
| 42 | |||
| 43 | if (kvaddr >= (void *)FIXADDR_START && | 63 | if (kvaddr >= (void *)FIXADDR_START && |
| 44 | kvaddr < (void *)FIXADDR_TOP) { | 64 | kvaddr < (void *)FIXADDR_TOP) { |
| 45 | type = kmap_atomic_idx(); | 65 | int idx = kmap_idx(kmap_atomic_idx(), |
| 46 | idx = type + KM_TYPE_NR * smp_processor_id(); | 66 | DCACHE_ALIAS((unsigned long)kvaddr)); |
| 47 | 67 | ||
| 48 | /* | 68 | /* |
| 49 | * Force other mappings to Oops if they'll try to access this | 69 | * Force other mappings to Oops if they'll try to access this |
| @@ -51,7 +71,7 @@ void __kunmap_atomic(void *kvaddr) | |||
| 51 | * is a bad idea also, in case the page changes cacheability | 71 | * is a bad idea also, in case the page changes cacheability |
| 52 | * attributes or becomes a protected page in a hypervisor. | 72 | * attributes or becomes a protected page in a hypervisor. |
| 53 | */ | 73 | */ |
| 54 | pte_clear(&init_mm, kvaddr, kmap_pte - idx); | 74 | pte_clear(&init_mm, kvaddr, kmap_pte + idx); |
| 55 | local_flush_tlb_kernel_range((unsigned long)kvaddr, | 75 | local_flush_tlb_kernel_range((unsigned long)kvaddr, |
| 56 | (unsigned long)kvaddr + PAGE_SIZE); | 76 | (unsigned long)kvaddr + PAGE_SIZE); |
| 57 | 77 | ||
| @@ -69,4 +89,5 @@ void __init kmap_init(void) | |||
| 69 | /* cache the first kmap pte */ | 89 | /* cache the first kmap pte */ |
| 70 | kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); | 90 | kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN); |
| 71 | kmap_pte = kmap_get_fixmap_pte(kmap_vstart); | 91 | kmap_pte = kmap_get_fixmap_pte(kmap_vstart); |
| 92 | kmap_waitqueues_init(); | ||
| 72 | } | 93 | } |
diff --git a/arch/xtensa/mm/misc.S b/arch/xtensa/mm/misc.S index 1f68558dbcc2..11a01c3e9cea 100644 --- a/arch/xtensa/mm/misc.S +++ b/arch/xtensa/mm/misc.S | |||
| @@ -110,41 +110,24 @@ ENTRY(__tlbtemp_mapping_start) | |||
| 110 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) | 110 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) |
| 111 | 111 | ||
| 112 | /* | 112 | /* |
| 113 | * clear_user_page (void *addr, unsigned long vaddr, struct page *page) | 113 | * clear_page_alias(void *addr, unsigned long paddr) |
| 114 | * a2 a3 a4 | 114 | * a2 a3 |
| 115 | */ | 115 | */ |
| 116 | 116 | ||
| 117 | ENTRY(clear_user_page) | 117 | ENTRY(clear_page_alias) |
| 118 | 118 | ||
| 119 | entry a1, 32 | 119 | entry a1, 32 |
| 120 | 120 | ||
| 121 | /* Mark page dirty and determine alias. */ | 121 | /* Skip setting up a temporary DTLB if not aliased low page. */ |
| 122 | 122 | ||
| 123 | movi a7, (1 << PG_ARCH_1) | 123 | movi a5, PAGE_OFFSET |
| 124 | l32i a5, a4, PAGE_FLAGS | 124 | movi a6, 0 |
| 125 | xor a6, a2, a3 | 125 | beqz a3, 1f |
| 126 | extui a3, a3, PAGE_SHIFT, DCACHE_ALIAS_ORDER | ||
| 127 | extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER | ||
| 128 | or a5, a5, a7 | ||
| 129 | slli a3, a3, PAGE_SHIFT | ||
| 130 | s32i a5, a4, PAGE_FLAGS | ||
| 131 | 126 | ||
| 132 | /* Skip setting up a temporary DTLB if not aliased. */ | 127 | /* Setup a temporary DTLB for the addr. */ |
| 133 | |||
| 134 | beqz a6, 1f | ||
| 135 | |||
| 136 | /* Invalidate kernel page. */ | ||
| 137 | |||
| 138 | mov a10, a2 | ||
| 139 | call8 __invalidate_dcache_page | ||
| 140 | |||
| 141 | /* Setup a temporary DTLB with the color of the VPN */ | ||
| 142 | |||
| 143 | movi a4, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff | ||
| 144 | movi a5, TLBTEMP_BASE_1 # virt | ||
| 145 | add a6, a2, a4 # ppn | ||
| 146 | add a2, a5, a3 # add 'color' | ||
| 147 | 128 | ||
| 129 | addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) | ||
| 130 | mov a4, a2 | ||
| 148 | wdtlb a6, a2 | 131 | wdtlb a6, a2 |
| 149 | dsync | 132 | dsync |
| 150 | 133 | ||
| @@ -165,62 +148,43 @@ ENTRY(clear_user_page) | |||
| 165 | 148 | ||
| 166 | /* We need to invalidate the temporary idtlb entry, if any. */ | 149 | /* We need to invalidate the temporary idtlb entry, if any. */ |
| 167 | 150 | ||
| 168 | 1: addi a2, a2, -PAGE_SIZE | 151 | 1: idtlb a4 |
| 169 | idtlb a2 | ||
| 170 | dsync | 152 | dsync |
| 171 | 153 | ||
| 172 | retw | 154 | retw |
| 173 | 155 | ||
| 174 | ENDPROC(clear_user_page) | 156 | ENDPROC(clear_page_alias) |
| 175 | 157 | ||
| 176 | /* | 158 | /* |
| 177 | * copy_page_user (void *to, void *from, unsigned long vaddr, struct page *page) | 159 | * copy_page_alias(void *to, void *from, |
| 178 | * a2 a3 a4 a5 | 160 | * a2 a3 |
| 161 | * unsigned long to_paddr, unsigned long from_paddr) | ||
| 162 | * a4 a5 | ||
| 179 | */ | 163 | */ |
| 180 | 164 | ||
| 181 | ENTRY(copy_user_page) | 165 | ENTRY(copy_page_alias) |
| 182 | 166 | ||
| 183 | entry a1, 32 | 167 | entry a1, 32 |
| 184 | 168 | ||
| 185 | /* Mark page dirty and determine alias for destination. */ | 169 | /* Skip setting up a temporary DTLB for destination if not aliased. */ |
| 186 | |||
| 187 | movi a8, (1 << PG_ARCH_1) | ||
| 188 | l32i a9, a5, PAGE_FLAGS | ||
| 189 | xor a6, a2, a4 | ||
| 190 | xor a7, a3, a4 | ||
| 191 | extui a4, a4, PAGE_SHIFT, DCACHE_ALIAS_ORDER | ||
| 192 | extui a6, a6, PAGE_SHIFT, DCACHE_ALIAS_ORDER | ||
| 193 | extui a7, a7, PAGE_SHIFT, DCACHE_ALIAS_ORDER | ||
| 194 | or a9, a9, a8 | ||
| 195 | slli a4, a4, PAGE_SHIFT | ||
| 196 | s32i a9, a5, PAGE_FLAGS | ||
| 197 | movi a5, ((PAGE_KERNEL | _PAGE_HW_WRITE) - PAGE_OFFSET) & 0xffffffff | ||
| 198 | |||
| 199 | beqz a6, 1f | ||
| 200 | |||
| 201 | /* Invalidate dcache */ | ||
| 202 | |||
| 203 | mov a10, a2 | ||
| 204 | call8 __invalidate_dcache_page | ||
| 205 | 170 | ||
| 206 | /* Setup a temporary DTLB with a matching color. */ | 171 | movi a6, 0 |
| 172 | movi a7, 0 | ||
| 173 | beqz a4, 1f | ||
| 207 | 174 | ||
| 208 | movi a8, TLBTEMP_BASE_1 # base | 175 | /* Setup a temporary DTLB for destination. */ |
| 209 | add a6, a2, a5 # ppn | ||
| 210 | add a2, a8, a4 # add 'color' | ||
| 211 | 176 | ||
| 177 | addi a6, a4, (PAGE_KERNEL | _PAGE_HW_WRITE) | ||
| 212 | wdtlb a6, a2 | 178 | wdtlb a6, a2 |
| 213 | dsync | 179 | dsync |
| 214 | 180 | ||
| 215 | /* Skip setting up a temporary DTLB for destination if not aliased. */ | 181 | /* Skip setting up a temporary DTLB for source if not aliased. */ |
| 216 | 182 | ||
| 217 | 1: beqz a7, 1f | 183 | 1: beqz a5, 1f |
| 218 | 184 | ||
| 219 | /* Setup a temporary DTLB with a matching color. */ | 185 | /* Setup a temporary DTLB for source. */ |
| 220 | 186 | ||
| 221 | movi a8, TLBTEMP_BASE_2 # base | 187 | addi a7, a5, PAGE_KERNEL |
| 222 | add a7, a3, a5 # ppn | ||
| 223 | add a3, a8, a4 | ||
| 224 | addi a8, a3, 1 # way1 | 188 | addi a8, a3, 1 # way1 |
| 225 | 189 | ||
| 226 | wdtlb a7, a8 | 190 | wdtlb a7, a8 |
| @@ -271,7 +235,7 @@ ENTRY(copy_user_page) | |||
| 271 | 235 | ||
| 272 | retw | 236 | retw |
| 273 | 237 | ||
| 274 | ENDPROC(copy_user_page) | 238 | ENDPROC(copy_page_alias) |
| 275 | 239 | ||
| 276 | #endif | 240 | #endif |
| 277 | 241 | ||
| @@ -300,6 +264,30 @@ ENTRY(__flush_invalidate_dcache_page_alias) | |||
| 300 | retw | 264 | retw |
| 301 | 265 | ||
| 302 | ENDPROC(__flush_invalidate_dcache_page_alias) | 266 | ENDPROC(__flush_invalidate_dcache_page_alias) |
| 267 | |||
| 268 | /* | ||
| 269 | * void __invalidate_dcache_page_alias (addr, phys) | ||
| 270 | * a2 a3 | ||
| 271 | */ | ||
| 272 | |||
| 273 | ENTRY(__invalidate_dcache_page_alias) | ||
| 274 | |||
| 275 | entry sp, 16 | ||
| 276 | |||
| 277 | movi a7, 0 # required for exception handler | ||
| 278 | addi a6, a3, (PAGE_KERNEL | _PAGE_HW_WRITE) | ||
| 279 | mov a4, a2 | ||
| 280 | wdtlb a6, a2 | ||
| 281 | dsync | ||
| 282 | |||
| 283 | ___invalidate_dcache_page a2 a3 | ||
| 284 | |||
| 285 | idtlb a4 | ||
| 286 | dsync | ||
| 287 | |||
| 288 | retw | ||
| 289 | |||
| 290 | ENDPROC(__invalidate_dcache_page_alias) | ||
| 303 | #endif | 291 | #endif |
| 304 | 292 | ||
| 305 | ENTRY(__tlbtemp_mapping_itlb) | 293 | ENTRY(__tlbtemp_mapping_itlb) |
diff --git a/arch/xtensa/mm/mmu.c b/arch/xtensa/mm/mmu.c index 3429b483d9f8..abe4513eb0dd 100644 --- a/arch/xtensa/mm/mmu.c +++ b/arch/xtensa/mm/mmu.c | |||
| @@ -18,32 +18,38 @@ | |||
| 18 | #include <asm/io.h> | 18 | #include <asm/io.h> |
| 19 | 19 | ||
| 20 | #if defined(CONFIG_HIGHMEM) | 20 | #if defined(CONFIG_HIGHMEM) |
| 21 | static void * __init init_pmd(unsigned long vaddr) | 21 | static void * __init init_pmd(unsigned long vaddr, unsigned long n_pages) |
| 22 | { | 22 | { |
| 23 | pgd_t *pgd = pgd_offset_k(vaddr); | 23 | pgd_t *pgd = pgd_offset_k(vaddr); |
| 24 | pmd_t *pmd = pmd_offset(pgd, vaddr); | 24 | pmd_t *pmd = pmd_offset(pgd, vaddr); |
| 25 | pte_t *pte; | ||
| 26 | unsigned long i; | ||
| 25 | 27 | ||
| 26 | if (pmd_none(*pmd)) { | 28 | n_pages = ALIGN(n_pages, PTRS_PER_PTE); |
| 27 | unsigned i; | ||
| 28 | pte_t *pte = alloc_bootmem_low_pages(PAGE_SIZE); | ||
| 29 | 29 | ||
| 30 | for (i = 0; i < 1024; i++) | 30 | pr_debug("%s: vaddr: 0x%08lx, n_pages: %ld\n", |
| 31 | pte_clear(NULL, 0, pte + i); | 31 | __func__, vaddr, n_pages); |
| 32 | 32 | ||
| 33 | set_pmd(pmd, __pmd(((unsigned long)pte) & PAGE_MASK)); | 33 | pte = alloc_bootmem_low_pages(n_pages * sizeof(pte_t)); |
| 34 | BUG_ON(pte != pte_offset_kernel(pmd, 0)); | 34 | |
| 35 | pr_debug("%s: vaddr: 0x%08lx, pmd: 0x%p, pte: 0x%p\n", | 35 | for (i = 0; i < n_pages; ++i) |
| 36 | __func__, vaddr, pmd, pte); | 36 | pte_clear(NULL, 0, pte + i); |
| 37 | return pte; | 37 | |
| 38 | } else { | 38 | for (i = 0; i < n_pages; i += PTRS_PER_PTE, ++pmd) { |
| 39 | return pte_offset_kernel(pmd, 0); | 39 | pte_t *cur_pte = pte + i; |
| 40 | |||
| 41 | BUG_ON(!pmd_none(*pmd)); | ||
| 42 | set_pmd(pmd, __pmd(((unsigned long)cur_pte) & PAGE_MASK)); | ||
| 43 | BUG_ON(cur_pte != pte_offset_kernel(pmd, 0)); | ||
| 44 | pr_debug("%s: pmd: 0x%p, pte: 0x%p\n", | ||
| 45 | __func__, pmd, cur_pte); | ||
| 40 | } | 46 | } |
| 47 | return pte; | ||
| 41 | } | 48 | } |
| 42 | 49 | ||
| 43 | static void __init fixedrange_init(void) | 50 | static void __init fixedrange_init(void) |
| 44 | { | 51 | { |
| 45 | BUILD_BUG_ON(FIXADDR_SIZE > PMD_SIZE); | 52 | init_pmd(__fix_to_virt(0), __end_of_fixed_addresses); |
| 46 | init_pmd(__fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK); | ||
| 47 | } | 53 | } |
| 48 | #endif | 54 | #endif |
| 49 | 55 | ||
| @@ -52,7 +58,7 @@ void __init paging_init(void) | |||
| 52 | memset(swapper_pg_dir, 0, PAGE_SIZE); | 58 | memset(swapper_pg_dir, 0, PAGE_SIZE); |
| 53 | #ifdef CONFIG_HIGHMEM | 59 | #ifdef CONFIG_HIGHMEM |
| 54 | fixedrange_init(); | 60 | fixedrange_init(); |
| 55 | pkmap_page_table = init_pmd(PKMAP_BASE); | 61 | pkmap_page_table = init_pmd(PKMAP_BASE, LAST_PKMAP); |
| 56 | kmap_init(); | 62 | kmap_init(); |
| 57 | #endif | 63 | #endif |
| 58 | } | 64 | } |
