diff options
Diffstat (limited to 'arch/arm/include')
| -rw-r--r-- | arch/arm/include/asm/assembler.h | 8 | ||||
| -rw-r--r-- | arch/arm/include/asm/dma-mapping.h | 7 | ||||
| -rw-r--r-- | arch/arm/include/asm/memory.h | 3 | ||||
| -rw-r--r-- | arch/arm/include/asm/pgtable.h | 40 | ||||
| -rw-r--r-- | arch/arm/include/asm/sched_clock.h | 2 | ||||
| -rw-r--r-- | arch/arm/include/asm/tlb.h | 4 | ||||
| -rw-r--r-- | arch/arm/include/asm/uaccess.h | 58 |
7 files changed, 88 insertions, 34 deletions
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0d..5c8b3bf4d825 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h | |||
| @@ -320,4 +320,12 @@ | |||
| 320 | .size \name , . - \name | 320 | .size \name , . - \name |
| 321 | .endm | 321 | .endm |
| 322 | 322 | ||
| 323 | .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req | ||
| 324 | #ifndef CONFIG_CPU_USE_DOMAINS | ||
| 325 | adds \tmp, \addr, #\size - 1 | ||
| 326 | sbcccs \tmp, \tmp, \limit | ||
| 327 | bcs \bad | ||
| 328 | #endif | ||
| 329 | .endm | ||
| 330 | |||
| 323 | #endif /* __ASM_ASSEMBLER_H__ */ | 331 | #endif /* __ASM_ASSEMBLER_H__ */ |
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index 2ae842df4551..5c44dcb0987b 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h | |||
| @@ -203,6 +203,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size, | |||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | /* | 205 | /* |
| 206 | * This can be called during early boot to increase the size of the atomic | ||
| 207 | * coherent DMA pool above the default value of 256KiB. It must be called | ||
| 208 | * before postcore_initcall. | ||
| 209 | */ | ||
| 210 | extern void __init init_dma_coherent_pool_size(unsigned long size); | ||
| 211 | |||
| 212 | /* | ||
| 206 | * This can be called during boot to increase the size of the consistent | 213 | * This can be called during boot to increase the size of the consistent |
| 207 | * DMA region above it's default value of 2MB. It must be called before the | 214 | * DMA region above it's default value of 2MB. It must be called before the |
| 208 | * memory allocator is initialised, i.e. before any core_initcall. | 215 | * memory allocator is initialised, i.e. before any core_initcall. |
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index e965f1b560f1..5f6ddcc56452 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h | |||
| @@ -187,6 +187,7 @@ static inline unsigned long __phys_to_virt(unsigned long x) | |||
| 187 | #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) | 187 | #define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET) |
| 188 | #endif | 188 | #endif |
| 189 | #endif | 189 | #endif |
| 190 | #endif /* __ASSEMBLY__ */ | ||
| 190 | 191 | ||
| 191 | #ifndef PHYS_OFFSET | 192 | #ifndef PHYS_OFFSET |
| 192 | #ifdef PLAT_PHYS_OFFSET | 193 | #ifdef PLAT_PHYS_OFFSET |
| @@ -196,6 +197,8 @@ static inline unsigned long __phys_to_virt(unsigned long x) | |||
| 196 | #endif | 197 | #endif |
| 197 | #endif | 198 | #endif |
| 198 | 199 | ||
| 200 | #ifndef __ASSEMBLY__ | ||
| 201 | |||
| 199 | /* | 202 | /* |
| 200 | * PFNs are used to describe any physical page; this means | 203 | * PFNs are used to describe any physical page; this means |
| 201 | * PFN 0 == physical address 0. | 204 | * PFN 0 == physical address 0. |
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index f66626d71e7d..41dc31f834c3 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
| @@ -195,6 +195,18 @@ static inline pte_t *pmd_page_vaddr(pmd_t pmd) | |||
| 195 | 195 | ||
| 196 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) | 196 | #define pte_clear(mm,addr,ptep) set_pte_ext(ptep, __pte(0), 0) |
| 197 | 197 | ||
| 198 | #define pte_none(pte) (!pte_val(pte)) | ||
| 199 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) | ||
| 200 | #define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) | ||
| 201 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) | ||
| 202 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) | ||
| 203 | #define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) | ||
| 204 | #define pte_special(pte) (0) | ||
| 205 | |||
| 206 | #define pte_present_user(pte) \ | ||
| 207 | ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ | ||
| 208 | (L_PTE_PRESENT | L_PTE_USER)) | ||
| 209 | |||
| 198 | #if __LINUX_ARM_ARCH__ < 6 | 210 | #if __LINUX_ARM_ARCH__ < 6 |
| 199 | static inline void __sync_icache_dcache(pte_t pteval) | 211 | static inline void __sync_icache_dcache(pte_t pteval) |
| 200 | { | 212 | { |
| @@ -206,25 +218,15 @@ extern void __sync_icache_dcache(pte_t pteval); | |||
| 206 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, | 218 | static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
| 207 | pte_t *ptep, pte_t pteval) | 219 | pte_t *ptep, pte_t pteval) |
| 208 | { | 220 | { |
| 209 | if (addr >= TASK_SIZE) | 221 | unsigned long ext = 0; |
| 210 | set_pte_ext(ptep, pteval, 0); | 222 | |
| 211 | else { | 223 | if (addr < TASK_SIZE && pte_present_user(pteval)) { |
| 212 | __sync_icache_dcache(pteval); | 224 | __sync_icache_dcache(pteval); |
| 213 | set_pte_ext(ptep, pteval, PTE_EXT_NG); | 225 | ext |= PTE_EXT_NG; |
| 214 | } | 226 | } |
| 215 | } | ||
| 216 | 227 | ||
| 217 | #define pte_none(pte) (!pte_val(pte)) | 228 | set_pte_ext(ptep, pteval, ext); |
| 218 | #define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT) | 229 | } |
| 219 | #define pte_write(pte) (!(pte_val(pte) & L_PTE_RDONLY)) | ||
| 220 | #define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY) | ||
| 221 | #define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG) | ||
| 222 | #define pte_exec(pte) (!(pte_val(pte) & L_PTE_XN)) | ||
| 223 | #define pte_special(pte) (0) | ||
| 224 | |||
| 225 | #define pte_present_user(pte) \ | ||
| 226 | ((pte_val(pte) & (L_PTE_PRESENT | L_PTE_USER)) == \ | ||
| 227 | (L_PTE_PRESENT | L_PTE_USER)) | ||
| 228 | 230 | ||
| 229 | #define PTE_BIT_FUNC(fn,op) \ | 231 | #define PTE_BIT_FUNC(fn,op) \ |
| 230 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } | 232 | static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; } |
| @@ -251,13 +253,13 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
| 251 | * | 253 | * |
| 252 | * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 | 254 | * 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 |
| 253 | * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 | 255 | * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 |
| 254 | * <--------------- offset --------------------> <- type --> 0 0 0 | 256 | * <--------------- offset ----------------------> < type -> 0 0 0 |
| 255 | * | 257 | * |
| 256 | * This gives us up to 63 swap files and 32GB per swap file. Note that | 258 | * This gives us up to 31 swap files and 64GB per swap file. Note that |
| 257 | * the offset field is always non-zero. | 259 | * the offset field is always non-zero. |
| 258 | */ | 260 | */ |
| 259 | #define __SWP_TYPE_SHIFT 3 | 261 | #define __SWP_TYPE_SHIFT 3 |
| 260 | #define __SWP_TYPE_BITS 6 | 262 | #define __SWP_TYPE_BITS 5 |
| 261 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) | 263 | #define __SWP_TYPE_MASK ((1 << __SWP_TYPE_BITS) - 1) |
| 262 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) | 264 | #define __SWP_OFFSET_SHIFT (__SWP_TYPE_BITS + __SWP_TYPE_SHIFT) |
| 263 | 265 | ||
diff --git a/arch/arm/include/asm/sched_clock.h b/arch/arm/include/asm/sched_clock.h index e3f757263438..05b8e82ec9f5 100644 --- a/arch/arm/include/asm/sched_clock.h +++ b/arch/arm/include/asm/sched_clock.h | |||
| @@ -10,5 +10,7 @@ | |||
| 10 | 10 | ||
| 11 | extern void sched_clock_postinit(void); | 11 | extern void sched_clock_postinit(void); |
| 12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); | 12 | extern void setup_sched_clock(u32 (*read)(void), int bits, unsigned long rate); |
| 13 | extern void setup_sched_clock_needs_suspend(u32 (*read)(void), int bits, | ||
| 14 | unsigned long rate); | ||
| 13 | 15 | ||
| 14 | #endif | 16 | #endif |
diff --git a/arch/arm/include/asm/tlb.h b/arch/arm/include/asm/tlb.h index 314d4664eae7..99a19512ee26 100644 --- a/arch/arm/include/asm/tlb.h +++ b/arch/arm/include/asm/tlb.h | |||
| @@ -199,6 +199,9 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
| 199 | { | 199 | { |
| 200 | pgtable_page_dtor(pte); | 200 | pgtable_page_dtor(pte); |
| 201 | 201 | ||
| 202 | #ifdef CONFIG_ARM_LPAE | ||
| 203 | tlb_add_flush(tlb, addr); | ||
| 204 | #else | ||
| 202 | /* | 205 | /* |
| 203 | * With the classic ARM MMU, a pte page has two corresponding pmd | 206 | * With the classic ARM MMU, a pte page has two corresponding pmd |
| 204 | * entries, each covering 1MB. | 207 | * entries, each covering 1MB. |
| @@ -206,6 +209,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte, | |||
| 206 | addr &= PMD_MASK; | 209 | addr &= PMD_MASK; |
| 207 | tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); | 210 | tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE); |
| 208 | tlb_add_flush(tlb, addr + SZ_1M); | 211 | tlb_add_flush(tlb, addr + SZ_1M); |
| 212 | #endif | ||
| 209 | 213 | ||
| 210 | tlb_remove_page(tlb, pte); | 214 | tlb_remove_page(tlb, pte); |
| 211 | } | 215 | } |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 479a6352e0b5..77bd79f2ffdb 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
| @@ -101,28 +101,39 @@ extern int __get_user_1(void *); | |||
| 101 | extern int __get_user_2(void *); | 101 | extern int __get_user_2(void *); |
| 102 | extern int __get_user_4(void *); | 102 | extern int __get_user_4(void *); |
| 103 | 103 | ||
| 104 | #define __get_user_x(__r2,__p,__e,__s,__i...) \ | 104 | #define __GUP_CLOBBER_1 "lr", "cc" |
| 105 | #ifdef CONFIG_CPU_USE_DOMAINS | ||
| 106 | #define __GUP_CLOBBER_2 "ip", "lr", "cc" | ||
| 107 | #else | ||
| 108 | #define __GUP_CLOBBER_2 "lr", "cc" | ||
| 109 | #endif | ||
| 110 | #define __GUP_CLOBBER_4 "lr", "cc" | ||
| 111 | |||
| 112 | #define __get_user_x(__r2,__p,__e,__l,__s) \ | ||
| 105 | __asm__ __volatile__ ( \ | 113 | __asm__ __volatile__ ( \ |
| 106 | __asmeq("%0", "r0") __asmeq("%1", "r2") \ | 114 | __asmeq("%0", "r0") __asmeq("%1", "r2") \ |
| 115 | __asmeq("%3", "r1") \ | ||
| 107 | "bl __get_user_" #__s \ | 116 | "bl __get_user_" #__s \ |
| 108 | : "=&r" (__e), "=r" (__r2) \ | 117 | : "=&r" (__e), "=r" (__r2) \ |
| 109 | : "0" (__p) \ | 118 | : "0" (__p), "r" (__l) \ |
| 110 | : __i, "cc") | 119 | : __GUP_CLOBBER_##__s) |
| 111 | 120 | ||
| 112 | #define get_user(x,p) \ | 121 | #define __get_user_check(x,p) \ |
| 113 | ({ \ | 122 | ({ \ |
| 123 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ | ||
| 114 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ | 124 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ |
| 115 | register unsigned long __r2 asm("r2"); \ | 125 | register unsigned long __r2 asm("r2"); \ |
| 126 | register unsigned long __l asm("r1") = __limit; \ | ||
| 116 | register int __e asm("r0"); \ | 127 | register int __e asm("r0"); \ |
| 117 | switch (sizeof(*(__p))) { \ | 128 | switch (sizeof(*(__p))) { \ |
| 118 | case 1: \ | 129 | case 1: \ |
| 119 | __get_user_x(__r2, __p, __e, 1, "lr"); \ | 130 | __get_user_x(__r2, __p, __e, __l, 1); \ |
| 120 | break; \ | 131 | break; \ |
| 121 | case 2: \ | 132 | case 2: \ |
| 122 | __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ | 133 | __get_user_x(__r2, __p, __e, __l, 2); \ |
| 123 | break; \ | 134 | break; \ |
| 124 | case 4: \ | 135 | case 4: \ |
| 125 | __get_user_x(__r2, __p, __e, 4, "lr"); \ | 136 | __get_user_x(__r2, __p, __e, __l, 4); \ |
| 126 | break; \ | 137 | break; \ |
| 127 | default: __e = __get_user_bad(); break; \ | 138 | default: __e = __get_user_bad(); break; \ |
| 128 | } \ | 139 | } \ |
| @@ -130,42 +141,57 @@ extern int __get_user_4(void *); | |||
| 130 | __e; \ | 141 | __e; \ |
| 131 | }) | 142 | }) |
| 132 | 143 | ||
| 144 | #define get_user(x,p) \ | ||
| 145 | ({ \ | ||
| 146 | might_fault(); \ | ||
| 147 | __get_user_check(x,p); \ | ||
| 148 | }) | ||
| 149 | |||
| 133 | extern int __put_user_1(void *, unsigned int); | 150 | extern int __put_user_1(void *, unsigned int); |
| 134 | extern int __put_user_2(void *, unsigned int); | 151 | extern int __put_user_2(void *, unsigned int); |
| 135 | extern int __put_user_4(void *, unsigned int); | 152 | extern int __put_user_4(void *, unsigned int); |
| 136 | extern int __put_user_8(void *, unsigned long long); | 153 | extern int __put_user_8(void *, unsigned long long); |
| 137 | 154 | ||
| 138 | #define __put_user_x(__r2,__p,__e,__s) \ | 155 | #define __put_user_x(__r2,__p,__e,__l,__s) \ |
| 139 | __asm__ __volatile__ ( \ | 156 | __asm__ __volatile__ ( \ |
| 140 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ | 157 | __asmeq("%0", "r0") __asmeq("%2", "r2") \ |
| 158 | __asmeq("%3", "r1") \ | ||
| 141 | "bl __put_user_" #__s \ | 159 | "bl __put_user_" #__s \ |
| 142 | : "=&r" (__e) \ | 160 | : "=&r" (__e) \ |
| 143 | : "0" (__p), "r" (__r2) \ | 161 | : "0" (__p), "r" (__r2), "r" (__l) \ |
| 144 | : "ip", "lr", "cc") | 162 | : "ip", "lr", "cc") |
| 145 | 163 | ||
| 146 | #define put_user(x,p) \ | 164 | #define __put_user_check(x,p) \ |
| 147 | ({ \ | 165 | ({ \ |
| 166 | unsigned long __limit = current_thread_info()->addr_limit - 1; \ | ||
| 148 | register const typeof(*(p)) __r2 asm("r2") = (x); \ | 167 | register const typeof(*(p)) __r2 asm("r2") = (x); \ |
| 149 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ | 168 | register const typeof(*(p)) __user *__p asm("r0") = (p);\ |
| 169 | register unsigned long __l asm("r1") = __limit; \ | ||
| 150 | register int __e asm("r0"); \ | 170 | register int __e asm("r0"); \ |
| 151 | switch (sizeof(*(__p))) { \ | 171 | switch (sizeof(*(__p))) { \ |
| 152 | case 1: \ | 172 | case 1: \ |
| 153 | __put_user_x(__r2, __p, __e, 1); \ | 173 | __put_user_x(__r2, __p, __e, __l, 1); \ |
| 154 | break; \ | 174 | break; \ |
| 155 | case 2: \ | 175 | case 2: \ |
| 156 | __put_user_x(__r2, __p, __e, 2); \ | 176 | __put_user_x(__r2, __p, __e, __l, 2); \ |
| 157 | break; \ | 177 | break; \ |
| 158 | case 4: \ | 178 | case 4: \ |
| 159 | __put_user_x(__r2, __p, __e, 4); \ | 179 | __put_user_x(__r2, __p, __e, __l, 4); \ |
| 160 | break; \ | 180 | break; \ |
| 161 | case 8: \ | 181 | case 8: \ |
| 162 | __put_user_x(__r2, __p, __e, 8); \ | 182 | __put_user_x(__r2, __p, __e, __l, 8); \ |
| 163 | break; \ | 183 | break; \ |
| 164 | default: __e = __put_user_bad(); break; \ | 184 | default: __e = __put_user_bad(); break; \ |
| 165 | } \ | 185 | } \ |
| 166 | __e; \ | 186 | __e; \ |
| 167 | }) | 187 | }) |
| 168 | 188 | ||
| 189 | #define put_user(x,p) \ | ||
| 190 | ({ \ | ||
| 191 | might_fault(); \ | ||
| 192 | __put_user_check(x,p); \ | ||
| 193 | }) | ||
| 194 | |||
| 169 | #else /* CONFIG_MMU */ | 195 | #else /* CONFIG_MMU */ |
| 170 | 196 | ||
| 171 | /* | 197 | /* |
| @@ -219,6 +245,7 @@ do { \ | |||
| 219 | unsigned long __gu_addr = (unsigned long)(ptr); \ | 245 | unsigned long __gu_addr = (unsigned long)(ptr); \ |
| 220 | unsigned long __gu_val; \ | 246 | unsigned long __gu_val; \ |
| 221 | __chk_user_ptr(ptr); \ | 247 | __chk_user_ptr(ptr); \ |
| 248 | might_fault(); \ | ||
| 222 | switch (sizeof(*(ptr))) { \ | 249 | switch (sizeof(*(ptr))) { \ |
| 223 | case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ | 250 | case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \ |
| 224 | case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ | 251 | case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \ |
| @@ -300,6 +327,7 @@ do { \ | |||
| 300 | unsigned long __pu_addr = (unsigned long)(ptr); \ | 327 | unsigned long __pu_addr = (unsigned long)(ptr); \ |
| 301 | __typeof__(*(ptr)) __pu_val = (x); \ | 328 | __typeof__(*(ptr)) __pu_val = (x); \ |
| 302 | __chk_user_ptr(ptr); \ | 329 | __chk_user_ptr(ptr); \ |
| 330 | might_fault(); \ | ||
| 303 | switch (sizeof(*(ptr))) { \ | 331 | switch (sizeof(*(ptr))) { \ |
| 304 | case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ | 332 | case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \ |
| 305 | case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ | 333 | case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \ |
