diff options
Diffstat (limited to 'arch/xtensa')
28 files changed, 433 insertions, 146 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 0a1b95f81a32..7ea6451a3a33 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig | |||
@@ -6,10 +6,12 @@ config XTENSA | |||
6 | select ARCH_WANT_FRAME_POINTERS | 6 | select ARCH_WANT_FRAME_POINTERS |
7 | select HAVE_IDE | 7 | select HAVE_IDE |
8 | select GENERIC_ATOMIC64 | 8 | select GENERIC_ATOMIC64 |
9 | select GENERIC_CLOCKEVENTS | ||
9 | select HAVE_GENERIC_HARDIRQS | 10 | select HAVE_GENERIC_HARDIRQS |
10 | select VIRT_TO_BUS | 11 | select VIRT_TO_BUS |
11 | select GENERIC_IRQ_SHOW | 12 | select GENERIC_IRQ_SHOW |
12 | select GENERIC_CPU_DEVICES | 13 | select GENERIC_CPU_DEVICES |
14 | select GENERIC_SCHED_CLOCK | ||
13 | select MODULES_USE_ELF_RELA | 15 | select MODULES_USE_ELF_RELA |
14 | select GENERIC_PCI_IOMAP | 16 | select GENERIC_PCI_IOMAP |
15 | select ARCH_WANT_IPC_PARSE_VERSION | 17 | select ARCH_WANT_IPC_PARSE_VERSION |
@@ -17,6 +19,7 @@ config XTENSA | |||
17 | select CLONE_BACKWARDS | 19 | select CLONE_BACKWARDS |
18 | select IRQ_DOMAIN | 20 | select IRQ_DOMAIN |
19 | select HAVE_OPROFILE | 21 | select HAVE_OPROFILE |
22 | select HAVE_FUNCTION_TRACER | ||
20 | help | 23 | help |
21 | Xtensa processors are 32-bit RISC machines designed by Tensilica | 24 | Xtensa processors are 32-bit RISC machines designed by Tensilica |
22 | primarily for embedded systems. These processors are both | 25 | primarily for embedded systems. These processors are both |
diff --git a/arch/xtensa/Kconfig.debug b/arch/xtensa/Kconfig.debug index a34010e0e51c..af7da74d535f 100644 --- a/arch/xtensa/Kconfig.debug +++ b/arch/xtensa/Kconfig.debug | |||
@@ -2,6 +2,16 @@ menu "Kernel hacking" | |||
2 | 2 | ||
3 | source "lib/Kconfig.debug" | 3 | source "lib/Kconfig.debug" |
4 | 4 | ||
5 | config DEBUG_TLB_SANITY | ||
6 | bool "Debug TLB sanity" | ||
7 | depends on DEBUG_KERNEL | ||
8 | help | ||
9 | Enable this to turn on TLB sanity check on each entry to userspace. | ||
10 | This check can spot missing TLB invalidation/wrong PTE permissions/ | ||
11 | premature page freeing. | ||
12 | |||
13 | If unsure, say N. | ||
14 | |||
5 | config LD_NO_RELAX | 15 | config LD_NO_RELAX |
6 | bool "Disable linker relaxation" | 16 | bool "Disable linker relaxation" |
7 | default n | 17 | default n |
diff --git a/arch/xtensa/boot/.gitignore b/arch/xtensa/boot/.gitignore new file mode 100644 index 000000000000..be7655998b26 --- /dev/null +++ b/arch/xtensa/boot/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | uImage | ||
2 | zImage.redboot | ||
3 | *.dtb | ||
diff --git a/arch/xtensa/boot/boot-elf/.gitignore b/arch/xtensa/boot/boot-elf/.gitignore new file mode 100644 index 000000000000..5ff8fbb8561b --- /dev/null +++ b/arch/xtensa/boot/boot-elf/.gitignore | |||
@@ -0,0 +1 @@ | |||
boot.lds | |||
diff --git a/arch/xtensa/boot/lib/.gitignore b/arch/xtensa/boot/lib/.gitignore new file mode 100644 index 000000000000..1629a6167755 --- /dev/null +++ b/arch/xtensa/boot/lib/.gitignore | |||
@@ -0,0 +1,3 @@ | |||
1 | inffast.c | ||
2 | inflate.c | ||
3 | inftrees.c | ||
diff --git a/arch/xtensa/boot/lib/Makefile b/arch/xtensa/boot/lib/Makefile index ad8952e8a07f..6868f2ca6af8 100644 --- a/arch/xtensa/boot/lib/Makefile +++ b/arch/xtensa/boot/lib/Makefile | |||
@@ -7,6 +7,13 @@ zlib := inffast.c inflate.c inftrees.c | |||
7 | lib-y += $(zlib:.c=.o) zmem.o | 7 | lib-y += $(zlib:.c=.o) zmem.o |
8 | 8 | ||
9 | ccflags-y := -Ilib/zlib_inflate | 9 | ccflags-y := -Ilib/zlib_inflate |
10 | ifdef CONFIG_FUNCTION_TRACER | ||
11 | CFLAGS_REMOVE_inflate.o = -pg | ||
12 | CFLAGS_REMOVE_zmem.o = -pg | ||
13 | CFLAGS_REMOVE_inftrees.o = -pg | ||
14 | CFLAGS_REMOVE_inffast.o = -pg | ||
15 | endif | ||
16 | |||
10 | 17 | ||
11 | quiet_cmd_copy_zlib = COPY $@ | 18 | quiet_cmd_copy_zlib = COPY $@ |
12 | cmd_copy_zlib = cat $< > $@ | 19 | cmd_copy_zlib = cat $< > $@ |
diff --git a/arch/xtensa/include/asm/bootparam.h b/arch/xtensa/include/asm/bootparam.h index 0c25799facab..23392c5630ce 100644 --- a/arch/xtensa/include/asm/bootparam.h +++ b/arch/xtensa/include/asm/bootparam.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ | 20 | #define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/ |
21 | #define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ | 21 | #define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */ |
22 | #define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ | 22 | #define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */ |
23 | #define BP_TAG_SERIAL_BAUSRATE 0x1004 /* baud rate of current console. */ | 23 | #define BP_TAG_SERIAL_BAUDRATE 0x1004 /* baud rate of current console. */ |
24 | #define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ | 24 | #define BP_TAG_SERIAL_PORT 0x1005 /* serial device of current console */ |
25 | #define BP_TAG_FDT 0x1006 /* flat device tree addr */ | 25 | #define BP_TAG_FDT 0x1006 /* flat device tree addr */ |
26 | 26 | ||
diff --git a/arch/xtensa/include/asm/cmpxchg.h b/arch/xtensa/include/asm/cmpxchg.h index d9ab131bc1aa..370b26f38414 100644 --- a/arch/xtensa/include/asm/cmpxchg.h +++ b/arch/xtensa/include/asm/cmpxchg.h | |||
@@ -93,6 +93,7 @@ static inline unsigned long __cmpxchg_local(volatile void *ptr, | |||
93 | ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ | 93 | ((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr), (unsigned long)(o),\ |
94 | (unsigned long)(n), sizeof(*(ptr)))) | 94 | (unsigned long)(n), sizeof(*(ptr)))) |
95 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) | 95 | #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n)) |
96 | #define cmpxchg64(ptr, o, n) cmpxchg64_local((ptr), (o), (n)) | ||
96 | 97 | ||
97 | /* | 98 | /* |
98 | * xchg_u32 | 99 | * xchg_u32 |
diff --git a/arch/xtensa/include/asm/delay.h b/arch/xtensa/include/asm/delay.h index 61fc5faeb46c..3899610c1dff 100644 --- a/arch/xtensa/include/asm/delay.h +++ b/arch/xtensa/include/asm/delay.h | |||
@@ -12,7 +12,7 @@ | |||
12 | #ifndef _XTENSA_DELAY_H | 12 | #ifndef _XTENSA_DELAY_H |
13 | #define _XTENSA_DELAY_H | 13 | #define _XTENSA_DELAY_H |
14 | 14 | ||
15 | #include <asm/processor.h> | 15 | #include <asm/timex.h> |
16 | #include <asm/param.h> | 16 | #include <asm/param.h> |
17 | 17 | ||
18 | extern unsigned long loops_per_jiffy; | 18 | extern unsigned long loops_per_jiffy; |
@@ -24,24 +24,17 @@ static inline void __delay(unsigned long loops) | |||
24 | : "=r" (loops) : "0" (loops)); | 24 | : "=r" (loops) : "0" (loops)); |
25 | } | 25 | } |
26 | 26 | ||
27 | static __inline__ u32 xtensa_get_ccount(void) | ||
28 | { | ||
29 | u32 ccount; | ||
30 | asm volatile ("rsr %0, ccount\n" : "=r" (ccount)); | ||
31 | return ccount; | ||
32 | } | ||
33 | |||
34 | /* For SMP/NUMA systems, change boot_cpu_data to something like | 27 | /* For SMP/NUMA systems, change boot_cpu_data to something like |
35 | * local_cpu_data->... where local_cpu_data points to the current | 28 | * local_cpu_data->... where local_cpu_data points to the current |
36 | * cpu. */ | 29 | * cpu. */ |
37 | 30 | ||
38 | static __inline__ void udelay (unsigned long usecs) | 31 | static __inline__ void udelay (unsigned long usecs) |
39 | { | 32 | { |
40 | unsigned long start = xtensa_get_ccount(); | 33 | unsigned long start = get_ccount(); |
41 | unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ)); | 34 | unsigned long cycles = usecs * (loops_per_jiffy / (1000000UL / HZ)); |
42 | 35 | ||
43 | /* Note: all variables are unsigned (can wrap around)! */ | 36 | /* Note: all variables are unsigned (can wrap around)! */ |
44 | while (((unsigned long)xtensa_get_ccount()) - start < cycles) | 37 | while (((unsigned long)get_ccount()) - start < cycles) |
45 | ; | 38 | ; |
46 | } | 39 | } |
47 | 40 | ||
diff --git a/arch/xtensa/include/asm/ftrace.h b/arch/xtensa/include/asm/ftrace.h index 36dc7a684397..73cc3f482304 100644 --- a/arch/xtensa/include/asm/ftrace.h +++ b/arch/xtensa/include/asm/ftrace.h | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <asm/processor.h> | 13 | #include <asm/processor.h> |
14 | 14 | ||
15 | #define HAVE_ARCH_CALLER_ADDR | 15 | #define HAVE_ARCH_CALLER_ADDR |
16 | #ifndef __ASSEMBLY__ | ||
16 | #define CALLER_ADDR0 ({ unsigned long a0, a1; \ | 17 | #define CALLER_ADDR0 ({ unsigned long a0, a1; \ |
17 | __asm__ __volatile__ ( \ | 18 | __asm__ __volatile__ ( \ |
18 | "mov %0, a0\n" \ | 19 | "mov %0, a0\n" \ |
@@ -24,10 +25,22 @@ extern unsigned long return_address(unsigned level); | |||
24 | #define CALLER_ADDR1 return_address(1) | 25 | #define CALLER_ADDR1 return_address(1) |
25 | #define CALLER_ADDR2 return_address(2) | 26 | #define CALLER_ADDR2 return_address(2) |
26 | #define CALLER_ADDR3 return_address(3) | 27 | #define CALLER_ADDR3 return_address(3) |
27 | #else | 28 | #else /* CONFIG_FRAME_POINTER */ |
28 | #define CALLER_ADDR1 (0) | 29 | #define CALLER_ADDR1 (0) |
29 | #define CALLER_ADDR2 (0) | 30 | #define CALLER_ADDR2 (0) |
30 | #define CALLER_ADDR3 (0) | 31 | #define CALLER_ADDR3 (0) |
31 | #endif | 32 | #endif /* CONFIG_FRAME_POINTER */ |
33 | #endif /* __ASSEMBLY__ */ | ||
34 | |||
35 | #ifdef CONFIG_FUNCTION_TRACER | ||
36 | |||
37 | #define MCOUNT_ADDR ((unsigned long)(_mcount)) | ||
38 | #define MCOUNT_INSN_SIZE 3 | ||
39 | |||
40 | #ifndef __ASSEMBLY__ | ||
41 | extern void _mcount(void); | ||
42 | #define mcount _mcount | ||
43 | #endif /* __ASSEMBLY__ */ | ||
44 | #endif /* CONFIG_FUNCTION_TRACER */ | ||
32 | 45 | ||
33 | #endif /* _XTENSA_FTRACE_H */ | 46 | #endif /* _XTENSA_FTRACE_H */ |
diff --git a/arch/xtensa/include/asm/pgtable.h b/arch/xtensa/include/asm/pgtable.h index 8f017eb309bd..0fdf5d043f82 100644 --- a/arch/xtensa/include/asm/pgtable.h +++ b/arch/xtensa/include/asm/pgtable.h | |||
@@ -5,7 +5,7 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | * | 7 | * |
8 | * Copyright (C) 2001 - 2007 Tensilica Inc. | 8 | * Copyright (C) 2001 - 2013 Tensilica Inc. |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #ifndef _XTENSA_PGTABLE_H | 11 | #ifndef _XTENSA_PGTABLE_H |
@@ -64,41 +64,82 @@ | |||
64 | * Virtual memory area. We keep a distance to other memory regions to be | 64 | * Virtual memory area. We keep a distance to other memory regions to be |
65 | * on the safe side. We also use this area for cache aliasing. | 65 | * on the safe side. We also use this area for cache aliasing. |
66 | */ | 66 | */ |
67 | |||
68 | #define VMALLOC_START 0xC0000000 | 67 | #define VMALLOC_START 0xC0000000 |
69 | #define VMALLOC_END 0xC7FEFFFF | 68 | #define VMALLOC_END 0xC7FEFFFF |
70 | #define TLBTEMP_BASE_1 0xC7FF0000 | 69 | #define TLBTEMP_BASE_1 0xC7FF0000 |
71 | #define TLBTEMP_BASE_2 0xC7FF8000 | 70 | #define TLBTEMP_BASE_2 0xC7FF8000 |
72 | 71 | ||
73 | /* | 72 | /* |
74 | * Xtensa Linux config PTE layout (when present): | 73 | * For the Xtensa architecture, the PTE layout is as follows: |
75 | * 31-12: PPN | 74 | * |
76 | * 11-6: Software | 75 | * 31------12 11 10-9 8-6 5-4 3-2 1-0 |
77 | * 5-4: RING | 76 | * +-----------------------------------------+ |
78 | * 3-0: CA | 77 | * | | Software | HARDWARE | |
78 | * | PPN | ADW | RI |Attribute| | ||
79 | * +-----------------------------------------+ | ||
80 | * pte_none | MBZ | 01 | 11 | 00 | | ||
81 | * +-----------------------------------------+ | ||
82 | * present | PPN | 0 | 00 | ADW | RI | CA | wx | | ||
83 | * +- - - - - - - - - - - - - - - - - - - - -+ | ||
84 | * (PAGE_NONE)| PPN | 0 | 00 | ADW | 01 | 11 | 11 | | ||
85 | * +-----------------------------------------+ | ||
86 | * swap | index | type | 01 | 11 | 00 | | ||
87 | * +- - - - - - - - - - - - - - - - - - - - -+ | ||
88 | * file | file offset | 01 | 11 | 10 | | ||
89 | * +-----------------------------------------+ | ||
90 | * | ||
91 | * For T1050 hardware and earlier the layout differs for present and (PAGE_NONE) | ||
92 | * +-----------------------------------------+ | ||
93 | * present | PPN | 0 | 00 | ADW | RI | CA | w1 | | ||
94 | * +-----------------------------------------+ | ||
95 | * (PAGE_NONE)| PPN | 0 | 00 | ADW | 01 | 01 | 00 | | ||
96 | * +-----------------------------------------+ | ||
79 | * | 97 | * |
80 | * Similar to the Alpha and MIPS ports, we need to keep track of the ref | 98 | * Legend: |
81 | * and mod bits in software. We have a software "you can read | 99 | * PPN Physical Page Number |
82 | * from this page" bit, and a hardware one which actually lets the | 100 | * ADW software: accessed (young) / dirty / writable |
83 | * process read from the page. On the same token we have a software | 101 | * RI ring (0=privileged, 1=user, 2 and 3 are unused) |
84 | * writable bit and the real hardware one which actually lets the | 102 | * CA cache attribute: 00 bypass, 01 writeback, 10 writethrough |
85 | * process write to the page. | 103 | * (11 is invalid and used to mark pages that are not present) |
104 | * w page is writable (hw) | ||
105 | * x page is executable (hw) | ||
106 | * index swap offset / PAGE_SIZE (bit 11-31: 21 bits -> 8 GB) | ||
107 | * (note that the index is always non-zero) | ||
108 | * type swap type (5 bits -> 32 types) | ||
109 | * file offset 26-bit offset into the file, in increments of PAGE_SIZE | ||
86 | * | 110 | * |
87 | * See further below for PTE layout for swapped-out pages. | 111 | * Notes: |
112 | * - (PROT_NONE) is a special case of 'present' but causes an exception for | ||
113 | * any access (read, write, and execute). | ||
114 | * - 'multihit-exception' has the highest priority of all MMU exceptions, | ||
115 | * so the ring must be set to 'RING_USER' even for 'non-present' pages. | ||
116 | * - on older hardware, the exectuable flag was not supported and | ||
117 | * used as a 'valid' flag, so it needs to be always set. | ||
118 | * - we need to keep track of certain flags in software (dirty and young) | ||
119 | * to do this, we use write exceptions and have a separate software w-flag. | ||
120 | * - attribute value 1101 (and 1111 on T1050 and earlier) is reserved | ||
88 | */ | 121 | */ |
89 | 122 | ||
123 | #define _PAGE_ATTRIB_MASK 0xf | ||
124 | |||
90 | #define _PAGE_HW_EXEC (1<<0) /* hardware: page is executable */ | 125 | #define _PAGE_HW_EXEC (1<<0) /* hardware: page is executable */ |
91 | #define _PAGE_HW_WRITE (1<<1) /* hardware: page is writable */ | 126 | #define _PAGE_HW_WRITE (1<<1) /* hardware: page is writable */ |
92 | 127 | ||
93 | #define _PAGE_FILE (1<<1) /* non-linear mapping, if !present */ | ||
94 | #define _PAGE_PROTNONE (3<<0) /* special case for VM_PROT_NONE */ | ||
95 | |||
96 | /* None of these cache modes include MP coherency: */ | ||
97 | #define _PAGE_CA_BYPASS (0<<2) /* bypass, non-speculative */ | 128 | #define _PAGE_CA_BYPASS (0<<2) /* bypass, non-speculative */ |
98 | #define _PAGE_CA_WB (1<<2) /* write-back */ | 129 | #define _PAGE_CA_WB (1<<2) /* write-back */ |
99 | #define _PAGE_CA_WT (2<<2) /* write-through */ | 130 | #define _PAGE_CA_WT (2<<2) /* write-through */ |
100 | #define _PAGE_CA_MASK (3<<2) | 131 | #define _PAGE_CA_MASK (3<<2) |
101 | #define _PAGE_INVALID (3<<2) | 132 | #define _PAGE_CA_INVALID (3<<2) |
133 | |||
134 | /* We use invalid attribute values to distinguish special pte entries */ | ||
135 | #if XCHAL_HW_VERSION_MAJOR < 2000 | ||
136 | #define _PAGE_HW_VALID 0x01 /* older HW needed this bit set */ | ||
137 | #define _PAGE_NONE 0x04 | ||
138 | #else | ||
139 | #define _PAGE_HW_VALID 0x00 | ||
140 | #define _PAGE_NONE 0x0f | ||
141 | #endif | ||
142 | #define _PAGE_FILE (1<<1) /* file mapped page, only if !present */ | ||
102 | 143 | ||
103 | #define _PAGE_USER (1<<4) /* user access (ring=1) */ | 144 | #define _PAGE_USER (1<<4) /* user access (ring=1) */ |
104 | 145 | ||
@@ -108,19 +149,12 @@ | |||
108 | #define _PAGE_DIRTY (1<<7) /* software: page dirty */ | 149 | #define _PAGE_DIRTY (1<<7) /* software: page dirty */ |
109 | #define _PAGE_ACCESSED (1<<8) /* software: page accessed (read) */ | 150 | #define _PAGE_ACCESSED (1<<8) /* software: page accessed (read) */ |
110 | 151 | ||
111 | /* On older HW revisions, we always have to set bit 0 */ | ||
112 | #if XCHAL_HW_VERSION_MAJOR < 2000 | ||
113 | # define _PAGE_VALID (1<<0) | ||
114 | #else | ||
115 | # define _PAGE_VALID 0 | ||
116 | #endif | ||
117 | |||
118 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
119 | #define _PAGE_PRESENT (_PAGE_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) | ||
120 | |||
121 | #ifdef CONFIG_MMU | 152 | #ifdef CONFIG_MMU |
122 | 153 | ||
123 | #define PAGE_NONE __pgprot(_PAGE_INVALID | _PAGE_USER | _PAGE_PROTNONE) | 154 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
155 | #define _PAGE_PRESENT (_PAGE_HW_VALID | _PAGE_CA_WB | _PAGE_ACCESSED) | ||
156 | |||
157 | #define PAGE_NONE __pgprot(_PAGE_NONE | _PAGE_USER) | ||
124 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER) | 158 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER) |
125 | #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_HW_EXEC) | 159 | #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_HW_EXEC) |
126 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER) | 160 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER) |
@@ -132,9 +166,9 @@ | |||
132 | #define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT|_PAGE_HW_WRITE|_PAGE_HW_EXEC) | 166 | #define PAGE_KERNEL_EXEC __pgprot(_PAGE_PRESENT|_PAGE_HW_WRITE|_PAGE_HW_EXEC) |
133 | 167 | ||
134 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) | 168 | #if (DCACHE_WAY_SIZE > PAGE_SIZE) |
135 | # define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED) | 169 | # define _PAGE_DIRECTORY (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_BYPASS) |
136 | #else | 170 | #else |
137 | # define _PAGE_DIRECTORY (_PAGE_VALID | _PAGE_ACCESSED | _PAGE_CA_WB) | 171 | # define _PAGE_DIRECTORY (_PAGE_HW_VALID | _PAGE_ACCESSED | _PAGE_CA_WB) |
138 | #endif | 172 | #endif |
139 | 173 | ||
140 | #else /* no mmu */ | 174 | #else /* no mmu */ |
@@ -202,12 +236,16 @@ static inline void pgtable_cache_init(void) { } | |||
202 | /* | 236 | /* |
203 | * pte status. | 237 | * pte status. |
204 | */ | 238 | */ |
205 | #define pte_none(pte) (pte_val(pte) == _PAGE_INVALID) | 239 | # define pte_none(pte) (pte_val(pte) == (_PAGE_CA_INVALID | _PAGE_USER)) |
206 | #define pte_present(pte) \ | 240 | #if XCHAL_HW_VERSION_MAJOR < 2000 |
207 | (((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_INVALID) \ | 241 | # define pte_present(pte) ((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID) |
208 | || ((pte_val(pte) & _PAGE_PROTNONE) == _PAGE_PROTNONE)) | 242 | #else |
243 | # define pte_present(pte) \ | ||
244 | (((pte_val(pte) & _PAGE_CA_MASK) != _PAGE_CA_INVALID) \ | ||
245 | || ((pte_val(pte) & _PAGE_ATTRIB_MASK) == _PAGE_NONE)) | ||
246 | #endif | ||
209 | #define pte_clear(mm,addr,ptep) \ | 247 | #define pte_clear(mm,addr,ptep) \ |
210 | do { update_pte(ptep, __pte(_PAGE_INVALID)); } while(0) | 248 | do { update_pte(ptep, __pte(_PAGE_CA_INVALID | _PAGE_USER)); } while (0) |
211 | 249 | ||
212 | #define pmd_none(pmd) (!pmd_val(pmd)) | 250 | #define pmd_none(pmd) (!pmd_val(pmd)) |
213 | #define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK) | 251 | #define pmd_present(pmd) (pmd_val(pmd) & PAGE_MASK) |
@@ -328,35 +366,23 @@ ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | |||
328 | 366 | ||
329 | 367 | ||
330 | /* | 368 | /* |
331 | * Encode and decode a swap entry. | 369 | * Encode and decode a swap and file entry. |
332 | * | ||
333 | * Format of swap pte: | ||
334 | * bit 0 MBZ | ||
335 | * bit 1 page-file (must be zero) | ||
336 | * bits 2 - 3 page hw access mode (must be 11: _PAGE_INVALID) | ||
337 | * bits 4 - 5 ring protection (must be 01: _PAGE_USER) | ||
338 | * bits 6 - 10 swap type (5 bits -> 32 types) | ||
339 | * bits 11 - 31 swap offset / PAGE_SIZE (21 bits -> 8GB) | ||
340 | |||
341 | * Format of file pte: | ||
342 | * bit 0 MBZ | ||
343 | * bit 1 page-file (must be one: _PAGE_FILE) | ||
344 | * bits 2 - 3 page hw access mode (must be 11: _PAGE_INVALID) | ||
345 | * bits 4 - 5 ring protection (must be 01: _PAGE_USER) | ||
346 | * bits 6 - 31 file offset / PAGE_SIZE | ||
347 | */ | 370 | */ |
371 | #define SWP_TYPE_BITS 5 | ||
372 | #define MAX_SWAPFILES_CHECK() BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS) | ||
348 | 373 | ||
349 | #define __swp_type(entry) (((entry).val >> 6) & 0x1f) | 374 | #define __swp_type(entry) (((entry).val >> 6) & 0x1f) |
350 | #define __swp_offset(entry) ((entry).val >> 11) | 375 | #define __swp_offset(entry) ((entry).val >> 11) |
351 | #define __swp_entry(type,offs) \ | 376 | #define __swp_entry(type,offs) \ |
352 | ((swp_entry_t) {((type) << 6) | ((offs) << 11) | _PAGE_INVALID}) | 377 | ((swp_entry_t){((type) << 6) | ((offs) << 11) | \ |
378 | _PAGE_CA_INVALID | _PAGE_USER}) | ||
353 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) | 379 | #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) |
354 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) | 380 | #define __swp_entry_to_pte(x) ((pte_t) { (x).val }) |
355 | 381 | ||
356 | #define PTE_FILE_MAX_BITS 28 | 382 | #define PTE_FILE_MAX_BITS 26 |
357 | #define pte_to_pgoff(pte) (pte_val(pte) >> 4) | 383 | #define pte_to_pgoff(pte) (pte_val(pte) >> 6) |
358 | #define pgoff_to_pte(off) \ | 384 | #define pgoff_to_pte(off) \ |
359 | ((pte_t) { ((off) << 4) | _PAGE_INVALID | _PAGE_FILE }) | 385 | ((pte_t) { ((off) << 6) | _PAGE_CA_INVALID | _PAGE_FILE | _PAGE_USER }) |
360 | 386 | ||
361 | #endif /* !defined (__ASSEMBLY__) */ | 387 | #endif /* !defined (__ASSEMBLY__) */ |
362 | 388 | ||
diff --git a/arch/xtensa/include/asm/platform.h b/arch/xtensa/include/asm/platform.h index ec098b68fb9a..32e98f27ce97 100644 --- a/arch/xtensa/include/asm/platform.h +++ b/arch/xtensa/include/asm/platform.h | |||
@@ -30,11 +30,6 @@ extern void platform_init(bp_tag_t*); | |||
30 | extern void platform_setup (char **); | 30 | extern void platform_setup (char **); |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * platform_init_irq is called from init_IRQ. | ||
34 | */ | ||
35 | extern void platform_init_irq (void); | ||
36 | |||
37 | /* | ||
38 | * platform_restart is called to restart the system. | 33 | * platform_restart is called to restart the system. |
39 | */ | 34 | */ |
40 | extern void platform_restart (void); | 35 | extern void platform_restart (void); |
diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h index 3d35e5d0367e..69f901713fb6 100644 --- a/arch/xtensa/include/asm/timex.h +++ b/arch/xtensa/include/asm/timex.h | |||
@@ -35,19 +35,11 @@ | |||
35 | # error "Bad timer number for Linux configurations!" | 35 | # error "Bad timer number for Linux configurations!" |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #define LINUX_TIMER_MASK (1L << LINUX_TIMER_INT) | ||
39 | |||
40 | #define CLOCK_TICK_RATE 1193180 /* (everyone is using this value) */ | ||
41 | #define CLOCK_TICK_FACTOR 20 /* Factor of both 10^6 and CLOCK_TICK_RATE */ | ||
42 | |||
43 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 38 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
44 | extern unsigned long ccount_per_jiffy; | 39 | extern unsigned long ccount_freq; |
45 | extern unsigned long nsec_per_ccount; | 40 | #define CCOUNT_PER_JIFFY (ccount_freq / HZ) |
46 | #define CCOUNT_PER_JIFFY ccount_per_jiffy | ||
47 | #define NSEC_PER_CCOUNT nsec_per_ccount | ||
48 | #else | 41 | #else |
49 | #define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ)) | 42 | #define CCOUNT_PER_JIFFY (CONFIG_XTENSA_CPU_CLOCK*(1000000UL/HZ)) |
50 | #define NSEC_PER_CCOUNT (1000UL / CONFIG_XTENSA_CPU_CLOCK) | ||
51 | #endif | 43 | #endif |
52 | 44 | ||
53 | 45 | ||
diff --git a/arch/xtensa/kernel/.gitignore b/arch/xtensa/kernel/.gitignore new file mode 100644 index 000000000000..c5f676c3c224 --- /dev/null +++ b/arch/xtensa/kernel/.gitignore | |||
@@ -0,0 +1 @@ | |||
vmlinux.lds | |||
diff --git a/arch/xtensa/kernel/Makefile b/arch/xtensa/kernel/Makefile index 1e7fc87a94bb..f90265ec1ccc 100644 --- a/arch/xtensa/kernel/Makefile +++ b/arch/xtensa/kernel/Makefile | |||
@@ -11,6 +11,7 @@ obj-y := align.o coprocessor.o entry.o irq.o pci-dma.o platform.o process.o \ | |||
11 | obj-$(CONFIG_KGDB) += xtensa-stub.o | 11 | obj-$(CONFIG_KGDB) += xtensa-stub.o |
12 | obj-$(CONFIG_PCI) += pci.o | 12 | obj-$(CONFIG_PCI) += pci.o |
13 | obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o | 13 | obj-$(CONFIG_MODULES) += xtensa_ksyms.o module.o |
14 | obj-$(CONFIG_FUNCTION_TRACER) += mcount.o | ||
14 | 15 | ||
15 | AFLAGS_head.o += -mtext-section-literals | 16 | AFLAGS_head.o += -mtext-section-literals |
16 | 17 | ||
diff --git a/arch/xtensa/kernel/entry.S b/arch/xtensa/kernel/entry.S index 5082507d5631..9298742f0fd0 100644 --- a/arch/xtensa/kernel/entry.S +++ b/arch/xtensa/kernel/entry.S | |||
@@ -458,7 +458,7 @@ common_exception_return: | |||
458 | 458 | ||
459 | _bbsi.l a4, TIF_NEED_RESCHED, 3f | 459 | _bbsi.l a4, TIF_NEED_RESCHED, 3f |
460 | _bbsi.l a4, TIF_NOTIFY_RESUME, 2f | 460 | _bbsi.l a4, TIF_NOTIFY_RESUME, 2f |
461 | _bbci.l a4, TIF_SIGPENDING, 4f | 461 | _bbci.l a4, TIF_SIGPENDING, 5f |
462 | 462 | ||
463 | 2: l32i a4, a1, PT_DEPC | 463 | 2: l32i a4, a1, PT_DEPC |
464 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f | 464 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f |
@@ -476,6 +476,13 @@ common_exception_return: | |||
476 | callx4 a4 | 476 | callx4 a4 |
477 | j 1b | 477 | j 1b |
478 | 478 | ||
479 | 5: | ||
480 | #ifdef CONFIG_DEBUG_TLB_SANITY | ||
481 | l32i a4, a1, PT_DEPC | ||
482 | bgeui a4, VALID_DOUBLE_EXCEPTION_ADDRESS, 4f | ||
483 | movi a4, check_tlb_sanity | ||
484 | callx4 a4 | ||
485 | #endif | ||
479 | 4: /* Restore optional registers. */ | 486 | 4: /* Restore optional registers. */ |
480 | 487 | ||
481 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT | 488 | load_xtregs_opt a1 a2 a4 a5 a6 a7 PT_XTREGS_OPT |
@@ -1792,10 +1799,15 @@ ENTRY(fast_store_prohibited) | |||
1792 | l32i a0, a0, 0 | 1799 | l32i a0, a0, 0 |
1793 | beqz a0, 2f | 1800 | beqz a0, 2f |
1794 | 1801 | ||
1795 | /* Note that we assume _PAGE_WRITABLE_BIT is only set if pte is valid.*/ | 1802 | /* |
1803 | * Note that we test _PAGE_WRITABLE_BIT only if PTE is present | ||
1804 | * and is not PAGE_NONE. See pgtable.h for possible PTE layouts. | ||
1805 | */ | ||
1796 | 1806 | ||
1797 | _PTE_OFFSET(a0, a1, a4) | 1807 | _PTE_OFFSET(a0, a1, a4) |
1798 | l32i a4, a0, 0 # read pteval | 1808 | l32i a4, a0, 0 # read pteval |
1809 | movi a1, _PAGE_CA_INVALID | ||
1810 | ball a4, a1, 2f | ||
1799 | bbci.l a4, _PAGE_WRITABLE_BIT, 2f | 1811 | bbci.l a4, _PAGE_WRITABLE_BIT, 2f |
1800 | 1812 | ||
1801 | movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE | 1813 | movi a1, _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_HW_WRITE |
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index ef12c0e6fa25..7d740ebbe198 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S | |||
@@ -68,6 +68,15 @@ _SetupMMU: | |||
68 | 68 | ||
69 | #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX | 69 | #ifdef CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX |
70 | initialize_mmu | 70 | initialize_mmu |
71 | #if defined(CONFIG_MMU) && XCHAL_HAVE_PTP_MMU && XCHAL_HAVE_SPANNING_WAY | ||
72 | rsr a2, excsave1 | ||
73 | movi a3, 0x08000000 | ||
74 | bgeu a2, a3, 1f | ||
75 | movi a3, 0xd0000000 | ||
76 | add a2, a2, a3 | ||
77 | wsr a2, excsave1 | ||
78 | 1: | ||
79 | #endif | ||
71 | #endif | 80 | #endif |
72 | .end no-absolute-literals | 81 | .end no-absolute-literals |
73 | 82 | ||
diff --git a/arch/xtensa/kernel/mcount.S b/arch/xtensa/kernel/mcount.S new file mode 100644 index 000000000000..0eeda2e4a25e --- /dev/null +++ b/arch/xtensa/kernel/mcount.S | |||
@@ -0,0 +1,50 @@ | |||
1 | /* | ||
2 | * arch/xtensa/kernel/mcount.S | ||
3 | * | ||
4 | * Xtensa specific mcount support | ||
5 | * | ||
6 | * This file is subject to the terms and conditions of the GNU General Public | ||
7 | * License. See the file "COPYING" in the main directory of this archive | ||
8 | * for more details. | ||
9 | * | ||
10 | * Copyright (C) 2013 Tensilica Inc. | ||
11 | */ | ||
12 | |||
13 | #include <linux/linkage.h> | ||
14 | #include <asm/ftrace.h> | ||
15 | |||
16 | /* | ||
17 | * Entry condition: | ||
18 | * | ||
19 | * a2: a0 of the caller | ||
20 | */ | ||
21 | |||
22 | ENTRY(_mcount) | ||
23 | |||
24 | entry a1, 16 | ||
25 | |||
26 | movi a4, ftrace_trace_function | ||
27 | l32i a4, a4, 0 | ||
28 | movi a3, ftrace_stub | ||
29 | bne a3, a4, 1f | ||
30 | retw | ||
31 | |||
32 | 1: xor a7, a2, a1 | ||
33 | movi a3, 0x3fffffff | ||
34 | and a7, a7, a3 | ||
35 | xor a7, a7, a1 | ||
36 | |||
37 | xor a6, a0, a1 | ||
38 | and a6, a6, a3 | ||
39 | xor a6, a6, a1 | ||
40 | addi a6, a6, -MCOUNT_INSN_SIZE | ||
41 | callx4 a4 | ||
42 | |||
43 | retw | ||
44 | |||
45 | ENDPROC(_mcount) | ||
46 | |||
47 | ENTRY(ftrace_stub) | ||
48 | entry a1, 16 | ||
49 | retw | ||
50 | ENDPROC(ftrace_stub) | ||
diff --git a/arch/xtensa/kernel/pci.c b/arch/xtensa/kernel/pci.c index 126c18839409..5b3403388d7f 100644 --- a/arch/xtensa/kernel/pci.c +++ b/arch/xtensa/kernel/pci.c | |||
@@ -77,9 +77,9 @@ pcibios_align_resource(void *data, const struct resource *res, | |||
77 | 77 | ||
78 | if (res->flags & IORESOURCE_IO) { | 78 | if (res->flags & IORESOURCE_IO) { |
79 | if (size > 0x100) { | 79 | if (size > 0x100) { |
80 | printk(KERN_ERR "PCI: I/O Region %s/%d too large" | 80 | pr_err("PCI: I/O Region %s/%d too large (%u bytes)\n", |
81 | " (%ld bytes)\n", pci_name(dev), | 81 | pci_name(dev), dev->resource - res, |
82 | dev->resource - res, size); | 82 | size); |
83 | } | 83 | } |
84 | 84 | ||
85 | if (start & 0x300) | 85 | if (start & 0x300) |
@@ -174,7 +174,7 @@ static int __init pcibios_init(void) | |||
174 | struct pci_controller *pci_ctrl; | 174 | struct pci_controller *pci_ctrl; |
175 | struct list_head resources; | 175 | struct list_head resources; |
176 | struct pci_bus *bus; | 176 | struct pci_bus *bus; |
177 | int next_busno = 0, i; | 177 | int next_busno = 0; |
178 | 178 | ||
179 | printk("PCI: Probing PCI hardware\n"); | 179 | printk("PCI: Probing PCI hardware\n"); |
180 | 180 | ||
@@ -197,7 +197,7 @@ static int __init pcibios_init(void) | |||
197 | 197 | ||
198 | subsys_initcall(pcibios_init); | 198 | subsys_initcall(pcibios_init); |
199 | 199 | ||
200 | void __init pcibios_fixup_bus(struct pci_bus *bus) | 200 | void pcibios_fixup_bus(struct pci_bus *bus) |
201 | { | 201 | { |
202 | if (bus->parent) { | 202 | if (bus->parent) { |
203 | /* This is a subordinate bridge */ | 203 | /* This is a subordinate bridge */ |
diff --git a/arch/xtensa/kernel/platform.c b/arch/xtensa/kernel/platform.c index 2bd6c351f37c..1cf008284dd2 100644 --- a/arch/xtensa/kernel/platform.c +++ b/arch/xtensa/kernel/platform.c | |||
@@ -29,7 +29,6 @@ | |||
29 | */ | 29 | */ |
30 | 30 | ||
31 | _F(void, setup, (char** cmd), { }); | 31 | _F(void, setup, (char** cmd), { }); |
32 | _F(void, init_irq, (void), { }); | ||
33 | _F(void, restart, (void), { while(1); }); | 32 | _F(void, restart, (void), { while(1); }); |
34 | _F(void, halt, (void), { while(1); }); | 33 | _F(void, halt, (void), { while(1); }); |
35 | _F(void, power_off, (void), { while(1); }); | 34 | _F(void, power_off, (void), { while(1); }); |
@@ -42,6 +41,6 @@ _F(void, pcibios_init, (void), { }); | |||
42 | _F(void, calibrate_ccount, (void), | 41 | _F(void, calibrate_ccount, (void), |
43 | { | 42 | { |
44 | pr_err("ERROR: Cannot calibrate cpu frequency! Assuming 10MHz.\n"); | 43 | pr_err("ERROR: Cannot calibrate cpu frequency! Assuming 10MHz.\n"); |
45 | ccount_per_jiffy = 10 * (1000000UL/HZ); | 44 | ccount_freq = 10 * 1000000UL; |
46 | }); | 45 | }); |
47 | #endif | 46 | #endif |
diff --git a/arch/xtensa/kernel/setup.c b/arch/xtensa/kernel/setup.c index 6dd25ecde3f5..42a8bba0b0ea 100644 --- a/arch/xtensa/kernel/setup.c +++ b/arch/xtensa/kernel/setup.c | |||
@@ -152,8 +152,8 @@ static int __init parse_tag_initrd(const bp_tag_t* tag) | |||
152 | { | 152 | { |
153 | meminfo_t* mi; | 153 | meminfo_t* mi; |
154 | mi = (meminfo_t*)(tag->data); | 154 | mi = (meminfo_t*)(tag->data); |
155 | initrd_start = (void*)(mi->start); | 155 | initrd_start = __va(mi->start); |
156 | initrd_end = (void*)(mi->end); | 156 | initrd_end = __va(mi->end); |
157 | 157 | ||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
@@ -164,7 +164,7 @@ __tagtable(BP_TAG_INITRD, parse_tag_initrd); | |||
164 | 164 | ||
165 | static int __init parse_tag_fdt(const bp_tag_t *tag) | 165 | static int __init parse_tag_fdt(const bp_tag_t *tag) |
166 | { | 166 | { |
167 | dtb_start = (void *)(tag->data[0]); | 167 | dtb_start = __va(tag->data[0]); |
168 | return 0; | 168 | return 0; |
169 | } | 169 | } |
170 | 170 | ||
@@ -256,7 +256,7 @@ void __init early_init_devtree(void *params) | |||
256 | static void __init copy_devtree(void) | 256 | static void __init copy_devtree(void) |
257 | { | 257 | { |
258 | void *alloc = early_init_dt_alloc_memory_arch( | 258 | void *alloc = early_init_dt_alloc_memory_arch( |
259 | be32_to_cpu(initial_boot_params->totalsize), 0); | 259 | be32_to_cpu(initial_boot_params->totalsize), 8); |
260 | if (alloc) { | 260 | if (alloc) { |
261 | memcpy(alloc, initial_boot_params, | 261 | memcpy(alloc, initial_boot_params, |
262 | be32_to_cpu(initial_boot_params->totalsize)); | 262 | be32_to_cpu(initial_boot_params->totalsize)); |
diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index ffb474104311..bdbb17312526 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
17 | #include <linux/time.h> | 17 | #include <linux/time.h> |
18 | #include <linux/clocksource.h> | 18 | #include <linux/clocksource.h> |
19 | #include <linux/clockchips.h> | ||
19 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
20 | #include <linux/module.h> | 21 | #include <linux/module.h> |
21 | #include <linux/init.h> | 22 | #include <linux/init.h> |
@@ -23,13 +24,13 @@ | |||
23 | #include <linux/profile.h> | 24 | #include <linux/profile.h> |
24 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
25 | #include <linux/irqdomain.h> | 26 | #include <linux/irqdomain.h> |
27 | #include <linux/sched_clock.h> | ||
26 | 28 | ||
27 | #include <asm/timex.h> | 29 | #include <asm/timex.h> |
28 | #include <asm/platform.h> | 30 | #include <asm/platform.h> |
29 | 31 | ||
30 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 32 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
31 | unsigned long ccount_per_jiffy; /* per 1/HZ */ | 33 | unsigned long ccount_freq; /* ccount Hz */ |
32 | unsigned long nsec_per_ccount; /* nsec per ccount increment */ | ||
33 | #endif | 34 | #endif |
34 | 35 | ||
35 | static cycle_t ccount_read(struct clocksource *cs) | 36 | static cycle_t ccount_read(struct clocksource *cs) |
@@ -37,6 +38,11 @@ static cycle_t ccount_read(struct clocksource *cs) | |||
37 | return (cycle_t)get_ccount(); | 38 | return (cycle_t)get_ccount(); |
38 | } | 39 | } |
39 | 40 | ||
41 | static u32 notrace ccount_sched_clock_read(void) | ||
42 | { | ||
43 | return get_ccount(); | ||
44 | } | ||
45 | |||
40 | static struct clocksource ccount_clocksource = { | 46 | static struct clocksource ccount_clocksource = { |
41 | .name = "ccount", | 47 | .name = "ccount", |
42 | .rating = 200, | 48 | .rating = 200, |
@@ -44,29 +50,98 @@ static struct clocksource ccount_clocksource = { | |||
44 | .mask = CLOCKSOURCE_MASK(32), | 50 | .mask = CLOCKSOURCE_MASK(32), |
45 | }; | 51 | }; |
46 | 52 | ||
53 | static int ccount_timer_set_next_event(unsigned long delta, | ||
54 | struct clock_event_device *dev); | ||
55 | static void ccount_timer_set_mode(enum clock_event_mode mode, | ||
56 | struct clock_event_device *evt); | ||
57 | static struct ccount_timer_t { | ||
58 | struct clock_event_device evt; | ||
59 | int irq_enabled; | ||
60 | } ccount_timer = { | ||
61 | .evt = { | ||
62 | .name = "ccount_clockevent", | ||
63 | .features = CLOCK_EVT_FEAT_ONESHOT, | ||
64 | .rating = 300, | ||
65 | .set_next_event = ccount_timer_set_next_event, | ||
66 | .set_mode = ccount_timer_set_mode, | ||
67 | }, | ||
68 | }; | ||
69 | |||
70 | static int ccount_timer_set_next_event(unsigned long delta, | ||
71 | struct clock_event_device *dev) | ||
72 | { | ||
73 | unsigned long flags, next; | ||
74 | int ret = 0; | ||
75 | |||
76 | local_irq_save(flags); | ||
77 | next = get_ccount() + delta; | ||
78 | set_linux_timer(next); | ||
79 | if (next - get_ccount() > delta) | ||
80 | ret = -ETIME; | ||
81 | local_irq_restore(flags); | ||
82 | |||
83 | return ret; | ||
84 | } | ||
85 | |||
86 | static void ccount_timer_set_mode(enum clock_event_mode mode, | ||
87 | struct clock_event_device *evt) | ||
88 | { | ||
89 | struct ccount_timer_t *timer = | ||
90 | container_of(evt, struct ccount_timer_t, evt); | ||
91 | |||
92 | /* | ||
93 | * There is no way to disable the timer interrupt at the device level, | ||
94 | * only at the intenable register itself. Since enable_irq/disable_irq | ||
95 | * calls are nested, we need to make sure that these calls are | ||
96 | * balanced. | ||
97 | */ | ||
98 | switch (mode) { | ||
99 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
100 | case CLOCK_EVT_MODE_UNUSED: | ||
101 | if (timer->irq_enabled) { | ||
102 | disable_irq(evt->irq); | ||
103 | timer->irq_enabled = 0; | ||
104 | } | ||
105 | break; | ||
106 | case CLOCK_EVT_MODE_RESUME: | ||
107 | case CLOCK_EVT_MODE_ONESHOT: | ||
108 | if (!timer->irq_enabled) { | ||
109 | enable_irq(evt->irq); | ||
110 | timer->irq_enabled = 1; | ||
111 | } | ||
112 | default: | ||
113 | break; | ||
114 | } | ||
115 | } | ||
116 | |||
47 | static irqreturn_t timer_interrupt(int irq, void *dev_id); | 117 | static irqreturn_t timer_interrupt(int irq, void *dev_id); |
48 | static struct irqaction timer_irqaction = { | 118 | static struct irqaction timer_irqaction = { |
49 | .handler = timer_interrupt, | 119 | .handler = timer_interrupt, |
50 | .flags = IRQF_DISABLED, | 120 | .flags = IRQF_TIMER, |
51 | .name = "timer", | 121 | .name = "timer", |
122 | .dev_id = &ccount_timer, | ||
52 | }; | 123 | }; |
53 | 124 | ||
54 | void __init time_init(void) | 125 | void __init time_init(void) |
55 | { | 126 | { |
56 | unsigned int irq; | ||
57 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 127 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
58 | printk("Calibrating CPU frequency "); | 128 | printk("Calibrating CPU frequency "); |
59 | platform_calibrate_ccount(); | 129 | platform_calibrate_ccount(); |
60 | printk("%d.%02d MHz\n", (int)ccount_per_jiffy/(1000000/HZ), | 130 | printk("%d.%02d MHz\n", (int)ccount_freq/1000000, |
61 | (int)(ccount_per_jiffy/(10000/HZ))%100); | 131 | (int)(ccount_freq/10000)%100); |
62 | #endif | 132 | #endif |
63 | clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); | 133 | clocksource_register_hz(&ccount_clocksource, CCOUNT_PER_JIFFY * HZ); |
64 | 134 | ||
65 | /* Initialize the linux timer interrupt. */ | 135 | ccount_timer.evt.cpumask = cpumask_of(0); |
136 | ccount_timer.evt.irq = irq_create_mapping(NULL, LINUX_TIMER_INT); | ||
137 | if (WARN(!ccount_timer.evt.irq, "error: can't map timer irq")) | ||
138 | return; | ||
139 | clockevents_config_and_register(&ccount_timer.evt, ccount_freq, 0xf, | ||
140 | 0xffffffff); | ||
141 | setup_irq(ccount_timer.evt.irq, &timer_irqaction); | ||
142 | ccount_timer.irq_enabled = 1; | ||
66 | 143 | ||
67 | irq = irq_create_mapping(NULL, LINUX_TIMER_INT); | 144 | setup_sched_clock(ccount_sched_clock_read, 32, ccount_freq); |
68 | setup_irq(irq, &timer_irqaction); | ||
69 | set_linux_timer(get_ccount() + CCOUNT_PER_JIFFY); | ||
70 | } | 145 | } |
71 | 146 | ||
72 | /* | 147 | /* |
@@ -75,36 +150,14 @@ void __init time_init(void) | |||
75 | 150 | ||
76 | irqreturn_t timer_interrupt (int irq, void *dev_id) | 151 | irqreturn_t timer_interrupt (int irq, void *dev_id) |
77 | { | 152 | { |
153 | struct ccount_timer_t *timer = dev_id; | ||
154 | struct clock_event_device *evt = &timer->evt; | ||
78 | 155 | ||
79 | unsigned long next; | 156 | evt->event_handler(evt); |
80 | |||
81 | next = get_linux_timer(); | ||
82 | |||
83 | again: | ||
84 | while ((signed long)(get_ccount() - next) > 0) { | ||
85 | |||
86 | profile_tick(CPU_PROFILING); | ||
87 | #ifndef CONFIG_SMP | ||
88 | update_process_times(user_mode(get_irq_regs())); | ||
89 | #endif | ||
90 | |||
91 | xtime_update(1); /* Linux handler in kernel/time/timekeeping */ | ||
92 | |||
93 | /* Note that writing CCOMPARE clears the interrupt. */ | ||
94 | |||
95 | next += CCOUNT_PER_JIFFY; | ||
96 | set_linux_timer(next); | ||
97 | } | ||
98 | 157 | ||
99 | /* Allow platform to do something useful (Wdog). */ | 158 | /* Allow platform to do something useful (Wdog). */ |
100 | |||
101 | platform_heartbeat(); | 159 | platform_heartbeat(); |
102 | 160 | ||
103 | /* Make sure we didn't miss any tick... */ | ||
104 | |||
105 | if ((signed long)(get_ccount() - next) > 0) | ||
106 | goto again; | ||
107 | |||
108 | return IRQ_HANDLED; | 161 | return IRQ_HANDLED; |
109 | } | 162 | } |
110 | 163 | ||
diff --git a/arch/xtensa/kernel/xtensa_ksyms.c b/arch/xtensa/kernel/xtensa_ksyms.c index 42c53c87c204..d8507f812f46 100644 --- a/arch/xtensa/kernel/xtensa_ksyms.c +++ b/arch/xtensa/kernel/xtensa_ksyms.c | |||
@@ -124,3 +124,7 @@ extern long common_exception_return; | |||
124 | extern long _spill_registers; | 124 | extern long _spill_registers; |
125 | EXPORT_SYMBOL(common_exception_return); | 125 | EXPORT_SYMBOL(common_exception_return); |
126 | EXPORT_SYMBOL(_spill_registers); | 126 | EXPORT_SYMBOL(_spill_registers); |
127 | |||
128 | #ifdef CONFIG_FUNCTION_TRACER | ||
129 | EXPORT_SYMBOL(_mcount); | ||
130 | #endif | ||
diff --git a/arch/xtensa/mm/tlb.c b/arch/xtensa/mm/tlb.c index 5411aa67c68e..ca9d2366bf12 100644 --- a/arch/xtensa/mm/tlb.c +++ b/arch/xtensa/mm/tlb.c | |||
@@ -64,7 +64,7 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
64 | { | 64 | { |
65 | if (mm == current->active_mm) { | 65 | if (mm == current->active_mm) { |
66 | unsigned long flags; | 66 | unsigned long flags; |
67 | local_save_flags(flags); | 67 | local_irq_save(flags); |
68 | __get_new_mmu_context(mm); | 68 | __get_new_mmu_context(mm); |
69 | __load_mmu_context(mm); | 69 | __load_mmu_context(mm); |
70 | local_irq_restore(flags); | 70 | local_irq_restore(flags); |
@@ -94,7 +94,7 @@ void flush_tlb_range (struct vm_area_struct *vma, | |||
94 | printk("[tlbrange<%02lx,%08lx,%08lx>]\n", | 94 | printk("[tlbrange<%02lx,%08lx,%08lx>]\n", |
95 | (unsigned long)mm->context, start, end); | 95 | (unsigned long)mm->context, start, end); |
96 | #endif | 96 | #endif |
97 | local_save_flags(flags); | 97 | local_irq_save(flags); |
98 | 98 | ||
99 | if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) { | 99 | if (end-start + (PAGE_SIZE-1) <= _TLB_ENTRIES << PAGE_SHIFT) { |
100 | int oldpid = get_rasid_register(); | 100 | int oldpid = get_rasid_register(); |
@@ -128,9 +128,10 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) | |||
128 | if(mm->context == NO_CONTEXT) | 128 | if(mm->context == NO_CONTEXT) |
129 | return; | 129 | return; |
130 | 130 | ||
131 | local_save_flags(flags); | 131 | local_irq_save(flags); |
132 | 132 | ||
133 | oldpid = get_rasid_register(); | 133 | oldpid = get_rasid_register(); |
134 | set_rasid_register(ASID_INSERT(mm->context)); | ||
134 | 135 | ||
135 | if (vma->vm_flags & VM_EXEC) | 136 | if (vma->vm_flags & VM_EXEC) |
136 | invalidate_itlb_mapping(page); | 137 | invalidate_itlb_mapping(page); |
@@ -140,3 +141,116 @@ void flush_tlb_page (struct vm_area_struct *vma, unsigned long page) | |||
140 | 141 | ||
141 | local_irq_restore(flags); | 142 | local_irq_restore(flags); |
142 | } | 143 | } |
144 | |||
145 | #ifdef CONFIG_DEBUG_TLB_SANITY | ||
146 | |||
147 | static unsigned get_pte_for_vaddr(unsigned vaddr) | ||
148 | { | ||
149 | struct task_struct *task = get_current(); | ||
150 | struct mm_struct *mm = task->mm; | ||
151 | pgd_t *pgd; | ||
152 | pmd_t *pmd; | ||
153 | pte_t *pte; | ||
154 | |||
155 | if (!mm) | ||
156 | mm = task->active_mm; | ||
157 | pgd = pgd_offset(mm, vaddr); | ||
158 | if (pgd_none_or_clear_bad(pgd)) | ||
159 | return 0; | ||
160 | pmd = pmd_offset(pgd, vaddr); | ||
161 | if (pmd_none_or_clear_bad(pmd)) | ||
162 | return 0; | ||
163 | pte = pte_offset_map(pmd, vaddr); | ||
164 | if (!pte) | ||
165 | return 0; | ||
166 | return pte_val(*pte); | ||
167 | } | ||
168 | |||
169 | enum { | ||
170 | TLB_SUSPICIOUS = 1, | ||
171 | TLB_INSANE = 2, | ||
172 | }; | ||
173 | |||
174 | static void tlb_insane(void) | ||
175 | { | ||
176 | BUG_ON(1); | ||
177 | } | ||
178 | |||
179 | static void tlb_suspicious(void) | ||
180 | { | ||
181 | WARN_ON(1); | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * Check that TLB entries with kernel ASID (1) have kernel VMA (>= TASK_SIZE), | ||
186 | * and TLB entries with user ASID (>=4) have VMA < TASK_SIZE. | ||
187 | * | ||
188 | * Check that valid TLB entries either have the same PA as the PTE, or PTE is | ||
189 | * marked as non-present. Non-present PTE and the page with non-zero refcount | ||
190 | * and zero mapcount is normal for batched TLB flush operation. Zero refcount | ||
191 | * means that the page was freed prematurely. Non-zero mapcount is unusual, | ||
192 | * but does not necessary means an error, thus marked as suspicious. | ||
193 | */ | ||
194 | static int check_tlb_entry(unsigned w, unsigned e, bool dtlb) | ||
195 | { | ||
196 | unsigned tlbidx = w | (e << PAGE_SHIFT); | ||
197 | unsigned r0 = dtlb ? | ||
198 | read_dtlb_virtual(tlbidx) : read_itlb_virtual(tlbidx); | ||
199 | unsigned vpn = (r0 & PAGE_MASK) | (e << PAGE_SHIFT); | ||
200 | unsigned pte = get_pte_for_vaddr(vpn); | ||
201 | unsigned mm_asid = (get_rasid_register() >> 8) & ASID_MASK; | ||
202 | unsigned tlb_asid = r0 & ASID_MASK; | ||
203 | bool kernel = tlb_asid == 1; | ||
204 | int rc = 0; | ||
205 | |||
206 | if (tlb_asid > 0 && ((vpn < TASK_SIZE) == kernel)) { | ||
207 | pr_err("%cTLB: way: %u, entry: %u, VPN %08x in %s PTE\n", | ||
208 | dtlb ? 'D' : 'I', w, e, vpn, | ||
209 | kernel ? "kernel" : "user"); | ||
210 | rc |= TLB_INSANE; | ||
211 | } | ||
212 | |||
213 | if (tlb_asid == mm_asid) { | ||
214 | unsigned r1 = dtlb ? read_dtlb_translation(tlbidx) : | ||
215 | read_itlb_translation(tlbidx); | ||
216 | if ((pte ^ r1) & PAGE_MASK) { | ||
217 | pr_err("%cTLB: way: %u, entry: %u, mapping: %08x->%08x, PTE: %08x\n", | ||
218 | dtlb ? 'D' : 'I', w, e, r0, r1, pte); | ||
219 | if (pte == 0 || !pte_present(__pte(pte))) { | ||
220 | struct page *p = pfn_to_page(r1 >> PAGE_SHIFT); | ||
221 | pr_err("page refcount: %d, mapcount: %d\n", | ||
222 | page_count(p), | ||
223 | page_mapcount(p)); | ||
224 | if (!page_count(p)) | ||
225 | rc |= TLB_INSANE; | ||
226 | else if (page_mapped(p)) | ||
227 | rc |= TLB_SUSPICIOUS; | ||
228 | } else { | ||
229 | rc |= TLB_INSANE; | ||
230 | } | ||
231 | } | ||
232 | } | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | void check_tlb_sanity(void) | ||
237 | { | ||
238 | unsigned long flags; | ||
239 | unsigned w, e; | ||
240 | int bug = 0; | ||
241 | |||
242 | local_irq_save(flags); | ||
243 | for (w = 0; w < DTLB_ARF_WAYS; ++w) | ||
244 | for (e = 0; e < (1 << XCHAL_DTLB_ARF_ENTRIES_LOG2); ++e) | ||
245 | bug |= check_tlb_entry(w, e, true); | ||
246 | for (w = 0; w < ITLB_ARF_WAYS; ++w) | ||
247 | for (e = 0; e < (1 << XCHAL_ITLB_ARF_ENTRIES_LOG2); ++e) | ||
248 | bug |= check_tlb_entry(w, e, false); | ||
249 | if (bug & TLB_INSANE) | ||
250 | tlb_insane(); | ||
251 | if (bug & TLB_SUSPICIOUS) | ||
252 | tlb_suspicious(); | ||
253 | local_irq_restore(flags); | ||
254 | } | ||
255 | |||
256 | #endif /* CONFIG_DEBUG_TLB_SANITY */ | ||
diff --git a/arch/xtensa/platforms/iss/network.c b/arch/xtensa/platforms/iss/network.c index 7d0fea6d7f20..56f88b7afe2f 100644 --- a/arch/xtensa/platforms/iss/network.c +++ b/arch/xtensa/platforms/iss/network.c | |||
@@ -700,7 +700,7 @@ struct iss_net_init { | |||
700 | 700 | ||
701 | #define ERR KERN_ERR "iss_net_setup: " | 701 | #define ERR KERN_ERR "iss_net_setup: " |
702 | 702 | ||
703 | static int iss_net_setup(char *str) | 703 | static int __init iss_net_setup(char *str) |
704 | { | 704 | { |
705 | struct iss_net_private *device = NULL; | 705 | struct iss_net_private *device = NULL; |
706 | struct iss_net_init *new; | 706 | struct iss_net_init *new; |
diff --git a/arch/xtensa/platforms/iss/simdisk.c b/arch/xtensa/platforms/iss/simdisk.c index c0edb35424ce..8c6e819cd8ed 100644 --- a/arch/xtensa/platforms/iss/simdisk.c +++ b/arch/xtensa/platforms/iss/simdisk.c | |||
@@ -108,13 +108,13 @@ static int simdisk_xfer_bio(struct simdisk *dev, struct bio *bio) | |||
108 | sector_t sector = bio->bi_sector; | 108 | sector_t sector = bio->bi_sector; |
109 | 109 | ||
110 | bio_for_each_segment(bvec, bio, i) { | 110 | bio_for_each_segment(bvec, bio, i) { |
111 | char *buffer = __bio_kmap_atomic(bio, i, KM_USER0); | 111 | char *buffer = __bio_kmap_atomic(bio, i); |
112 | unsigned len = bvec->bv_len >> SECTOR_SHIFT; | 112 | unsigned len = bvec->bv_len >> SECTOR_SHIFT; |
113 | 113 | ||
114 | simdisk_transfer(dev, sector, len, buffer, | 114 | simdisk_transfer(dev, sector, len, buffer, |
115 | bio_data_dir(bio) == WRITE); | 115 | bio_data_dir(bio) == WRITE); |
116 | sector += len; | 116 | sector += len; |
117 | __bio_kunmap_atomic(bio, KM_USER0); | 117 | __bio_kunmap_atomic(bio); |
118 | } | 118 | } |
119 | return 0; | 119 | return 0; |
120 | } | 120 | } |
diff --git a/arch/xtensa/platforms/xtfpga/setup.c b/arch/xtensa/platforms/xtfpga/setup.c index 96ef8eeb064e..74bb74fa3f87 100644 --- a/arch/xtensa/platforms/xtfpga/setup.c +++ b/arch/xtensa/platforms/xtfpga/setup.c | |||
@@ -163,7 +163,7 @@ void platform_heartbeat(void) | |||
163 | 163 | ||
164 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT | 164 | #ifdef CONFIG_XTENSA_CALIBRATE_CCOUNT |
165 | 165 | ||
166 | void platform_calibrate_ccount(void) | 166 | void __init platform_calibrate_ccount(void) |
167 | { | 167 | { |
168 | long clk_freq = 0; | 168 | long clk_freq = 0; |
169 | #ifdef CONFIG_OF | 169 | #ifdef CONFIG_OF |
@@ -179,8 +179,7 @@ void platform_calibrate_ccount(void) | |||
179 | if (!clk_freq) | 179 | if (!clk_freq) |
180 | clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; | 180 | clk_freq = *(long *)XTFPGA_CLKFRQ_VADDR; |
181 | 181 | ||
182 | ccount_per_jiffy = clk_freq / HZ; | 182 | ccount_freq = clk_freq; |
183 | nsec_per_ccount = 1000000000UL / clk_freq; | ||
184 | } | 183 | } |
185 | 184 | ||
186 | #endif | 185 | #endif |
diff --git a/arch/xtensa/variants/s6000/delay.c b/arch/xtensa/variants/s6000/delay.c index 54b2b573f166..39154563ee17 100644 --- a/arch/xtensa/variants/s6000/delay.c +++ b/arch/xtensa/variants/s6000/delay.c | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <asm/delay.h> | ||
2 | #include <asm/timex.h> | 1 | #include <asm/timex.h> |
3 | #include <asm/io.h> | 2 | #include <asm/io.h> |
4 | #include <variant/hardware.h> | 3 | #include <variant/hardware.h> |
@@ -17,11 +16,10 @@ void platform_calibrate_ccount(void) | |||
17 | "1: l32i %0, %2, 0 ;" | 16 | "1: l32i %0, %2, 0 ;" |
18 | " beq %0, %1, 1b ;" | 17 | " beq %0, %1, 1b ;" |
19 | : "=&a"(u) : "a"(t), "a"(tstamp)); | 18 | : "=&a"(u) : "a"(t), "a"(tstamp)); |
20 | b = xtensa_get_ccount(); | 19 | b = get_ccount(); |
21 | if (i == LOOPS) | 20 | if (i == LOOPS) |
22 | a = b; | 21 | a = b; |
23 | } while (--i >= 0); | 22 | } while (--i >= 0); |
24 | b -= a; | 23 | b -= a; |
25 | nsec_per_ccount = (LOOPS * 10000) / b; | 24 | ccount_freq = b * (100000UL / LOOPS); |
26 | ccount_per_jiffy = b * (100000UL / (LOOPS * HZ)); | ||
27 | } | 25 | } |