diff options
| -rw-r--r-- | arch/parisc/Makefile | 6 | ||||
| -rw-r--r-- | arch/parisc/include/asm/cacheflush.h | 5 | ||||
| -rw-r--r-- | arch/parisc/include/asm/pgtable.h | 47 | ||||
| -rw-r--r-- | arch/parisc/include/asm/uaccess.h | 14 | ||||
| -rw-r--r-- | arch/parisc/kernel/cache.c | 5 | ||||
| -rw-r--r-- | arch/parisc/kernel/parisc_ksyms.c | 2 | ||||
| -rw-r--r-- | arch/parisc/lib/Makefile | 3 | ||||
| -rw-r--r-- | arch/parisc/lib/ucmpdi2.c | 25 |
8 files changed, 67 insertions, 40 deletions
diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 01d95e2f0581..113e28206503 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile | |||
| @@ -65,8 +65,10 @@ ifndef CONFIG_FUNCTION_TRACER | |||
| 65 | endif | 65 | endif |
| 66 | 66 | ||
| 67 | # Use long jumps instead of long branches (needed if your linker fails to | 67 | # Use long jumps instead of long branches (needed if your linker fails to |
| 68 | # link a too big vmlinux executable) | 68 | # link a too big vmlinux executable). Not enabled for building modules. |
| 69 | cflags-$(CONFIG_MLONGCALLS) += -mlong-calls | 69 | ifdef CONFIG_MLONGCALLS |
| 70 | KBUILD_CFLAGS_KERNEL += -mlong-calls | ||
| 71 | endif | ||
| 70 | 72 | ||
| 71 | # select which processor to optimise for | 73 | # select which processor to optimise for |
| 72 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 | 74 | cflags-$(CONFIG_PA7100) += -march=1.1 -mschedule=7100 |
diff --git a/arch/parisc/include/asm/cacheflush.h b/arch/parisc/include/asm/cacheflush.h index 79f694f3ad9b..f0e2784e7cca 100644 --- a/arch/parisc/include/asm/cacheflush.h +++ b/arch/parisc/include/asm/cacheflush.h | |||
| @@ -140,7 +140,10 @@ static inline void *kmap(struct page *page) | |||
| 140 | return page_address(page); | 140 | return page_address(page); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | #define kunmap(page) kunmap_parisc(page_address(page)) | 143 | static inline void kunmap(struct page *page) |
| 144 | { | ||
| 145 | kunmap_parisc(page_address(page)); | ||
| 146 | } | ||
| 144 | 147 | ||
| 145 | static inline void *kmap_atomic(struct page *page) | 148 | static inline void *kmap_atomic(struct page *page) |
| 146 | { | 149 | { |
diff --git a/arch/parisc/include/asm/pgtable.h b/arch/parisc/include/asm/pgtable.h index 7df49fad29f9..1e40d7f86be3 100644 --- a/arch/parisc/include/asm/pgtable.h +++ b/arch/parisc/include/asm/pgtable.h | |||
| @@ -16,6 +16,8 @@ | |||
| 16 | #include <asm/processor.h> | 16 | #include <asm/processor.h> |
| 17 | #include <asm/cache.h> | 17 | #include <asm/cache.h> |
| 18 | 18 | ||
| 19 | extern spinlock_t pa_dbit_lock; | ||
| 20 | |||
| 19 | /* | 21 | /* |
| 20 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel | 22 | * kern_addr_valid(ADDR) tests if ADDR is pointing to valid kernel |
| 21 | * memory. For the return value to be meaningful, ADDR must be >= | 23 | * memory. For the return value to be meaningful, ADDR must be >= |
| @@ -44,8 +46,11 @@ extern void purge_tlb_entries(struct mm_struct *, unsigned long); | |||
| 44 | 46 | ||
| 45 | #define set_pte_at(mm, addr, ptep, pteval) \ | 47 | #define set_pte_at(mm, addr, ptep, pteval) \ |
| 46 | do { \ | 48 | do { \ |
| 49 | unsigned long flags; \ | ||
| 50 | spin_lock_irqsave(&pa_dbit_lock, flags); \ | ||
| 47 | set_pte(ptep, pteval); \ | 51 | set_pte(ptep, pteval); \ |
| 48 | purge_tlb_entries(mm, addr); \ | 52 | purge_tlb_entries(mm, addr); \ |
| 53 | spin_unlock_irqrestore(&pa_dbit_lock, flags); \ | ||
| 49 | } while (0) | 54 | } while (0) |
| 50 | 55 | ||
| 51 | #endif /* !__ASSEMBLY__ */ | 56 | #endif /* !__ASSEMBLY__ */ |
| @@ -435,48 +440,46 @@ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t *); | |||
| 435 | 440 | ||
| 436 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) | 441 | static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, pte_t *ptep) |
| 437 | { | 442 | { |
| 438 | #ifdef CONFIG_SMP | 443 | pte_t pte; |
| 444 | unsigned long flags; | ||
| 445 | |||
| 439 | if (!pte_young(*ptep)) | 446 | if (!pte_young(*ptep)) |
| 440 | return 0; | 447 | return 0; |
| 441 | return test_and_clear_bit(xlate_pabit(_PAGE_ACCESSED_BIT), &pte_val(*ptep)); | 448 | |
| 442 | #else | 449 | spin_lock_irqsave(&pa_dbit_lock, flags); |
| 443 | pte_t pte = *ptep; | 450 | pte = *ptep; |
| 444 | if (!pte_young(pte)) | 451 | if (!pte_young(pte)) { |
| 452 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | ||
| 445 | return 0; | 453 | return 0; |
| 446 | set_pte_at(vma->vm_mm, addr, ptep, pte_mkold(pte)); | 454 | } |
| 455 | set_pte(ptep, pte_mkold(pte)); | ||
| 456 | purge_tlb_entries(vma->vm_mm, addr); | ||
| 457 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | ||
| 447 | return 1; | 458 | return 1; |
| 448 | #endif | ||
| 449 | } | 459 | } |
| 450 | 460 | ||
| 451 | extern spinlock_t pa_dbit_lock; | ||
| 452 | |||
| 453 | struct mm_struct; | 461 | struct mm_struct; |
| 454 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 462 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
| 455 | { | 463 | { |
| 456 | pte_t old_pte; | 464 | pte_t old_pte; |
| 465 | unsigned long flags; | ||
| 457 | 466 | ||
| 458 | spin_lock(&pa_dbit_lock); | 467 | spin_lock_irqsave(&pa_dbit_lock, flags); |
| 459 | old_pte = *ptep; | 468 | old_pte = *ptep; |
| 460 | pte_clear(mm,addr,ptep); | 469 | pte_clear(mm,addr,ptep); |
| 461 | spin_unlock(&pa_dbit_lock); | 470 | purge_tlb_entries(mm, addr); |
| 471 | spin_unlock_irqrestore(&pa_dbit_lock, flags); | ||
| 462 | 472 | ||
| 463 | return old_pte; | 473 | return old_pte; |
| 464 | } | 474 | } |
| 465 | 475 | ||
| 466 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 476 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
| 467 | { | 477 | { |
| 468 | #ifdef CONFIG_SMP | 478 | unsigned long flags; |
| 469 | unsigned long new, old; | 479 | spin_lock_irqsave(&pa_dbit_lock, flags); |
| 470 | 480 | set_pte(ptep, pte_wrprotect(*ptep)); | |
| 471 | do { | ||
| 472 | old = pte_val(*ptep); | ||
| 473 | new = pte_val(pte_wrprotect(__pte (old))); | ||
| 474 | } while (cmpxchg((unsigned long *) ptep, old, new) != old); | ||
| 475 | purge_tlb_entries(mm, addr); | 481 | purge_tlb_entries(mm, addr); |
| 476 | #else | 482 | spin_unlock_irqrestore(&pa_dbit_lock, flags); |
| 477 | pte_t old_pte = *ptep; | ||
| 478 | set_pte_at(mm, addr, ptep, pte_wrprotect(old_pte)); | ||
| 479 | #endif | ||
| 480 | } | 483 | } |
| 481 | 484 | ||
| 482 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) | 485 | #define pte_same(A,B) (pte_val(A) == pte_val(B)) |
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h index 4ba2c93770f1..e0a82358517e 100644 --- a/arch/parisc/include/asm/uaccess.h +++ b/arch/parisc/include/asm/uaccess.h | |||
| @@ -181,30 +181,24 @@ struct exception_data { | |||
| 181 | #if !defined(CONFIG_64BIT) | 181 | #if !defined(CONFIG_64BIT) |
| 182 | 182 | ||
| 183 | #define __put_kernel_asm64(__val,ptr) do { \ | 183 | #define __put_kernel_asm64(__val,ptr) do { \ |
| 184 | u64 __val64 = (u64)(__val); \ | ||
| 185 | u32 hi = (__val64) >> 32; \ | ||
| 186 | u32 lo = (__val64) & 0xffffffff; \ | ||
| 187 | __asm__ __volatile__ ( \ | 184 | __asm__ __volatile__ ( \ |
| 188 | "\n1:\tstw %2,0(%1)" \ | 185 | "\n1:\tstw %2,0(%1)" \ |
| 189 | "\n2:\tstw %3,4(%1)\n\t" \ | 186 | "\n2:\tstw %R2,4(%1)\n\t" \ |
| 190 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ | 187 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ |
| 191 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ | 188 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ |
| 192 | : "=r"(__pu_err) \ | 189 | : "=r"(__pu_err) \ |
| 193 | : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \ | 190 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ |
| 194 | : "r1"); \ | 191 | : "r1"); \ |
| 195 | } while (0) | 192 | } while (0) |
| 196 | 193 | ||
| 197 | #define __put_user_asm64(__val,ptr) do { \ | 194 | #define __put_user_asm64(__val,ptr) do { \ |
| 198 | u64 __val64 = (u64)(__val); \ | ||
| 199 | u32 hi = (__val64) >> 32; \ | ||
| 200 | u32 lo = (__val64) & 0xffffffff; \ | ||
| 201 | __asm__ __volatile__ ( \ | 195 | __asm__ __volatile__ ( \ |
| 202 | "\n1:\tstw %2,0(%%sr3,%1)" \ | 196 | "\n1:\tstw %2,0(%%sr3,%1)" \ |
| 203 | "\n2:\tstw %3,4(%%sr3,%1)\n\t" \ | 197 | "\n2:\tstw %R2,4(%%sr3,%1)\n\t" \ |
| 204 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ | 198 | ASM_EXCEPTIONTABLE_ENTRY(1b,fixup_put_user_skip_2)\ |
| 205 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ | 199 | ASM_EXCEPTIONTABLE_ENTRY(2b,fixup_put_user_skip_1)\ |
| 206 | : "=r"(__pu_err) \ | 200 | : "=r"(__pu_err) \ |
| 207 | : "r"(ptr), "r"(hi), "r"(lo), "0"(__pu_err) \ | 201 | : "r"(ptr), "r"(__val), "0"(__pu_err) \ |
| 208 | : "r1"); \ | 202 | : "r1"); \ |
| 209 | } while (0) | 203 | } while (0) |
| 210 | 204 | ||
diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index 4b12890642eb..83ded26cad06 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c | |||
| @@ -421,14 +421,11 @@ void purge_tlb_entries(struct mm_struct *mm, unsigned long addr) | |||
| 421 | /* Note: purge_tlb_entries can be called at startup with | 421 | /* Note: purge_tlb_entries can be called at startup with |
| 422 | no context. */ | 422 | no context. */ |
| 423 | 423 | ||
| 424 | /* Disable preemption while we play with %sr1. */ | ||
| 425 | preempt_disable(); | ||
| 426 | mtsp(mm->context, 1); | ||
| 427 | purge_tlb_start(flags); | 424 | purge_tlb_start(flags); |
| 425 | mtsp(mm->context, 1); | ||
| 428 | pdtlb(addr); | 426 | pdtlb(addr); |
| 429 | pitlb(addr); | 427 | pitlb(addr); |
| 430 | purge_tlb_end(flags); | 428 | purge_tlb_end(flags); |
| 431 | preempt_enable(); | ||
| 432 | } | 429 | } |
| 433 | EXPORT_SYMBOL(purge_tlb_entries); | 430 | EXPORT_SYMBOL(purge_tlb_entries); |
| 434 | 431 | ||
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c index 6795dc6c995f..568b2c61ea02 100644 --- a/arch/parisc/kernel/parisc_ksyms.c +++ b/arch/parisc/kernel/parisc_ksyms.c | |||
| @@ -120,11 +120,13 @@ extern void __ashrdi3(void); | |||
| 120 | extern void __ashldi3(void); | 120 | extern void __ashldi3(void); |
| 121 | extern void __lshrdi3(void); | 121 | extern void __lshrdi3(void); |
| 122 | extern void __muldi3(void); | 122 | extern void __muldi3(void); |
| 123 | extern void __ucmpdi2(void); | ||
| 123 | 124 | ||
| 124 | EXPORT_SYMBOL(__ashrdi3); | 125 | EXPORT_SYMBOL(__ashrdi3); |
| 125 | EXPORT_SYMBOL(__ashldi3); | 126 | EXPORT_SYMBOL(__ashldi3); |
| 126 | EXPORT_SYMBOL(__lshrdi3); | 127 | EXPORT_SYMBOL(__lshrdi3); |
| 127 | EXPORT_SYMBOL(__muldi3); | 128 | EXPORT_SYMBOL(__muldi3); |
| 129 | EXPORT_SYMBOL(__ucmpdi2); | ||
| 128 | 130 | ||
| 129 | asmlinkage void * __canonicalize_funcptr_for_compare(void *); | 131 | asmlinkage void * __canonicalize_funcptr_for_compare(void *); |
| 130 | EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); | 132 | EXPORT_SYMBOL(__canonicalize_funcptr_for_compare); |
diff --git a/arch/parisc/lib/Makefile b/arch/parisc/lib/Makefile index 5f2e6904d14a..5651536ac733 100644 --- a/arch/parisc/lib/Makefile +++ b/arch/parisc/lib/Makefile | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | # Makefile for parisc-specific library files | 2 | # Makefile for parisc-specific library files |
| 3 | # | 3 | # |
| 4 | 4 | ||
| 5 | lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o | 5 | lib-y := lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o \ |
| 6 | ucmpdi2.o | ||
| 6 | 7 | ||
| 7 | obj-y := iomap.o | 8 | obj-y := iomap.o |
diff --git a/arch/parisc/lib/ucmpdi2.c b/arch/parisc/lib/ucmpdi2.c new file mode 100644 index 000000000000..149c016f32c5 --- /dev/null +++ b/arch/parisc/lib/ucmpdi2.c | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #include <linux/module.h> | ||
| 2 | |||
| 3 | union ull_union { | ||
| 4 | unsigned long long ull; | ||
| 5 | struct { | ||
| 6 | unsigned int high; | ||
| 7 | unsigned int low; | ||
| 8 | } ui; | ||
| 9 | }; | ||
| 10 | |||
| 11 | int __ucmpdi2(unsigned long long a, unsigned long long b) | ||
| 12 | { | ||
| 13 | union ull_union au = {.ull = a}; | ||
| 14 | union ull_union bu = {.ull = b}; | ||
| 15 | |||
| 16 | if (au.ui.high < bu.ui.high) | ||
| 17 | return 0; | ||
| 18 | else if (au.ui.high > bu.ui.high) | ||
| 19 | return 2; | ||
| 20 | if (au.ui.low < bu.ui.low) | ||
| 21 | return 0; | ||
| 22 | else if (au.ui.low > bu.ui.low) | ||
| 23 | return 2; | ||
| 24 | return 1; | ||
| 25 | } | ||
