aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/include/asm/pgtable.h6
-rw-r--r--arch/sh/kernel/process_64.c24
-rw-r--r--arch/sh/kernel/signal_64.c38
-rw-r--r--arch/sh/mm/fault_64.c11
-rw-r--r--arch/sh/mm/tlb-sh5.c21
-rw-r--r--arch/sh/mm/tlbflush_64.c2
6 files changed, 36 insertions, 66 deletions
diff --git a/arch/sh/include/asm/pgtable.h b/arch/sh/include/asm/pgtable.h
index 43ef3e99fdd1..3cd7127af957 100644
--- a/arch/sh/include/asm/pgtable.h
+++ b/arch/sh/include/asm/pgtable.h
@@ -36,6 +36,12 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
36#define NEFF_SIGN (1LL << (NEFF - 1)) 36#define NEFF_SIGN (1LL << (NEFF - 1))
37#define NEFF_MASK (-1LL << NEFF) 37#define NEFF_MASK (-1LL << NEFF)
38 38
39static inline unsigned long long neff_sign_extend(unsigned long val)
40{
41 unsigned long long extended = val;
42 return (extended & NEFF_SIGN) ? (extended | NEFF_MASK) : extended;
43}
44
39#ifdef CONFIG_29BIT 45#ifdef CONFIG_29BIT
40#define NPHYS 29 46#define NPHYS 29
41#else 47#else
diff --git a/arch/sh/kernel/process_64.c b/arch/sh/kernel/process_64.c
index 24de74214940..1192398ef582 100644
--- a/arch/sh/kernel/process_64.c
+++ b/arch/sh/kernel/process_64.c
@@ -425,7 +425,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
425 struct task_struct *p, struct pt_regs *regs) 425 struct task_struct *p, struct pt_regs *regs)
426{ 426{
427 struct pt_regs *childregs; 427 struct pt_regs *childregs;
428 unsigned long long se; /* Sign extension */
429 428
430#ifdef CONFIG_SH_FPU 429#ifdef CONFIG_SH_FPU
431 if(last_task_used_math == current) { 430 if(last_task_used_math == current) {
@@ -441,11 +440,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
441 440
442 *childregs = *regs; 441 *childregs = *regs;
443 442
443 /*
444 * Sign extend the edited stack.
445 * Note that thread.pc and thread.pc will stay
446 * 32-bit wide and context switch must take care
447 * of NEFF sign extension.
448 */
444 if (user_mode(regs)) { 449 if (user_mode(regs)) {
445 childregs->regs[15] = usp; 450 childregs->regs[15] = neff_sign_extend(usp);
446 p->thread.uregs = childregs; 451 p->thread.uregs = childregs;
447 } else { 452 } else {
448 childregs->regs[15] = (unsigned long)task_stack_page(p) + THREAD_SIZE; 453 childregs->regs[15] =
454 neff_sign_extend((unsigned long)task_stack_page(p) +
455 THREAD_SIZE);
449 } 456 }
450 457
451 childregs->regs[9] = 0; /* Set return value for child */ 458 childregs->regs[9] = 0; /* Set return value for child */
@@ -454,17 +461,6 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
454 p->thread.sp = (unsigned long) childregs; 461 p->thread.sp = (unsigned long) childregs;
455 p->thread.pc = (unsigned long) ret_from_fork; 462 p->thread.pc = (unsigned long) ret_from_fork;
456 463
457 /*
458 * Sign extend the edited stack.
459 * Note that thread.pc and thread.pc will stay
460 * 32-bit wide and context switch must take care
461 * of NEFF sign extension.
462 */
463
464 se = childregs->regs[15];
465 se = (se & NEFF_SIGN) ? (se | NEFF_MASK) : se;
466 childregs->regs[15] = se;
467
468 return 0; 464 return 0;
469} 465}
470 466
diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c
index 0663a0ee6021..026fd1cfe17d 100644
--- a/arch/sh/kernel/signal_64.c
+++ b/arch/sh/kernel/signal_64.c
@@ -561,13 +561,11 @@ static int setup_frame(int sig, struct k_sigaction *ka,
561 /* Set up to return from userspace. If provided, use a stub 561 /* Set up to return from userspace. If provided, use a stub
562 already in userspace. */ 562 already in userspace. */
563 if (ka->sa.sa_flags & SA_RESTORER) { 563 if (ka->sa.sa_flags & SA_RESTORER) {
564 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
565
566 /* 564 /*
567 * On SH5 all edited pointers are subject to NEFF 565 * On SH5 all edited pointers are subject to NEFF
568 */ 566 */
569 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? 567 DEREF_REG_PR = neff_sign_extend((unsigned long)
570 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; 568 ka->sa.sa_restorer | 0x1);
571 } else { 569 } else {
572 /* 570 /*
573 * Different approach on SH5. 571 * Different approach on SH5.
@@ -580,9 +578,8 @@ static int setup_frame(int sig, struct k_sigaction *ka,
580 * . being code, linker turns ShMedia bit on, always 578 * . being code, linker turns ShMedia bit on, always
581 * dereference index -1. 579 * dereference index -1.
582 */ 580 */
583 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; 581 DEREF_REG_PR = neff_sign_extend((unsigned long)
584 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? 582 frame->retcode | 0x01);
585 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
586 583
587 if (__copy_to_user(frame->retcode, 584 if (__copy_to_user(frame->retcode,
588 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0) 585 (void *)((unsigned long)sa_default_restorer & (~1)), 16) != 0)
@@ -596,9 +593,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
596 * Set up registers for signal handler. 593 * Set up registers for signal handler.
597 * All edited pointers are subject to NEFF. 594 * All edited pointers are subject to NEFF.
598 */ 595 */
599 regs->regs[REG_SP] = (unsigned long) frame; 596 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
600 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
601 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
602 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ 597 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
603 598
604 /* FIXME: 599 /* FIXME:
@@ -613,8 +608,7 @@ static int setup_frame(int sig, struct k_sigaction *ka,
613 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc; 608 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
614 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc; 609 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->sc;
615 610
616 regs->pc = (unsigned long) ka->sa.sa_handler; 611 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
617 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
618 612
619 set_fs(USER_DS); 613 set_fs(USER_DS);
620 614
@@ -676,13 +670,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
676 /* Set up to return from userspace. If provided, use a stub 670 /* Set up to return from userspace. If provided, use a stub
677 already in userspace. */ 671 already in userspace. */
678 if (ka->sa.sa_flags & SA_RESTORER) { 672 if (ka->sa.sa_flags & SA_RESTORER) {
679 DEREF_REG_PR = (unsigned long) ka->sa.sa_restorer | 0x1;
680
681 /* 673 /*
682 * On SH5 all edited pointers are subject to NEFF 674 * On SH5 all edited pointers are subject to NEFF
683 */ 675 */
684 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ? 676 DEREF_REG_PR = neff_sign_extend((unsigned long)
685 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR; 677 ka->sa.sa_restorer | 0x1);
686 } else { 678 } else {
687 /* 679 /*
688 * Different approach on SH5. 680 * Different approach on SH5.
@@ -695,15 +687,14 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
695 * . being code, linker turns ShMedia bit on, always 687 * . being code, linker turns ShMedia bit on, always
696 * dereference index -1. 688 * dereference index -1.
697 */ 689 */
698 690 DEREF_REG_PR = neff_sign_extend((unsigned long)
699 DEREF_REG_PR = (unsigned long) frame->retcode | 0x01; 691 frame->retcode | 0x01);
700 DEREF_REG_PR = (DEREF_REG_PR & NEFF_SIGN) ?
701 (DEREF_REG_PR | NEFF_MASK) : DEREF_REG_PR;
702 692
703 if (__copy_to_user(frame->retcode, 693 if (__copy_to_user(frame->retcode,
704 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0) 694 (void *)((unsigned long)sa_default_rt_restorer & (~1)), 16) != 0)
705 goto give_sigsegv; 695 goto give_sigsegv;
706 696
697 /* Cohere the trampoline with the I-cache. */
707 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15); 698 flush_icache_range(DEREF_REG_PR-1, DEREF_REG_PR-1+15);
708 } 699 }
709 700
@@ -711,14 +702,11 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
711 * Set up registers for signal handler. 702 * Set up registers for signal handler.
712 * All edited pointers are subject to NEFF. 703 * All edited pointers are subject to NEFF.
713 */ 704 */
714 regs->regs[REG_SP] = (unsigned long) frame; 705 regs->regs[REG_SP] = neff_sign_extend((unsigned long)frame);
715 regs->regs[REG_SP] = (regs->regs[REG_SP] & NEFF_SIGN) ?
716 (regs->regs[REG_SP] | NEFF_MASK) : regs->regs[REG_SP];
717 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */ 706 regs->regs[REG_ARG1] = signal; /* Arg for signal handler */
718 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info; 707 regs->regs[REG_ARG2] = (unsigned long long)(unsigned long)(signed long)&frame->info;
719 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext; 708 regs->regs[REG_ARG3] = (unsigned long long)(unsigned long)(signed long)&frame->uc.uc_mcontext;
720 regs->pc = (unsigned long) ka->sa.sa_handler; 709 regs->pc = neff_sign_extend((unsigned long)ka->sa.sa_handler);
721 regs->pc = (regs->pc & NEFF_SIGN) ? (regs->pc | NEFF_MASK) : regs->pc;
722 710
723 set_fs(USER_DS); 711 set_fs(USER_DS);
724 712
diff --git a/arch/sh/mm/fault_64.c b/arch/sh/mm/fault_64.c
index bd63b961b2a9..2b356cec2489 100644
--- a/arch/sh/mm/fault_64.c
+++ b/arch/sh/mm/fault_64.c
@@ -56,16 +56,7 @@ inline void __do_tlb_refill(unsigned long address,
56 /* 56 /*
57 * Set PTEH register 57 * Set PTEH register
58 */ 58 */
59 pteh = address & MMU_VPN_MASK; 59 pteh = neff_sign_extend(address & MMU_VPN_MASK);
60
61 /* Sign extend based on neff. */
62#if (NEFF == 32)
63 /* Faster sign extension */
64 pteh = (unsigned long long)(signed long long)(signed long)pteh;
65#else
66 /* General case */
67 pteh = (pteh & NEFF_SIGN) ? (pteh | NEFF_MASK) : pteh;
68#endif
69 60
70 /* Set the ASID. */ 61 /* Set the ASID. */
71 pteh |= get_asid() << PTEH_ASID_SHIFT; 62 pteh |= get_asid() << PTEH_ASID_SHIFT;
diff --git a/arch/sh/mm/tlb-sh5.c b/arch/sh/mm/tlb-sh5.c
index dae131243bcc..fdb64e41ec50 100644
--- a/arch/sh/mm/tlb-sh5.c
+++ b/arch/sh/mm/tlb-sh5.c
@@ -117,26 +117,15 @@ int sh64_put_wired_dtlb_entry(unsigned long long entry)
117 * Load up a virtual<->physical translation for @eaddr<->@paddr in the 117 * Load up a virtual<->physical translation for @eaddr<->@paddr in the
118 * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry). 118 * pre-allocated TLB slot @config_addr (see sh64_get_wired_dtlb_entry).
119 */ 119 */
120inline void sh64_setup_tlb_slot(unsigned long long config_addr, 120void sh64_setup_tlb_slot(unsigned long long config_addr, unsigned long eaddr,
121 unsigned long eaddr, 121 unsigned long asid, unsigned long paddr)
122 unsigned long asid,
123 unsigned long paddr)
124{ 122{
125 unsigned long long pteh, ptel; 123 unsigned long long pteh, ptel;
126 124
127 /* Sign extension */ 125 pteh = neff_sign_extend(eaddr);
128#if (NEFF == 32)
129 pteh = (unsigned long long)(signed long long)(signed long) eaddr;
130#else
131#error "Can't sign extend more than 32 bits yet"
132#endif
133 pteh &= PAGE_MASK; 126 pteh &= PAGE_MASK;
134 pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID; 127 pteh |= (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
135#if (NEFF == 32) 128 ptel = neff_sign_extend(paddr);
136 ptel = (unsigned long long)(signed long long)(signed long) paddr;
137#else
138#error "Can't sign extend more than 32 bits yet"
139#endif
140 ptel &= PAGE_MASK; 129 ptel &= PAGE_MASK;
141 ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE); 130 ptel |= (_PAGE_CACHABLE | _PAGE_READ | _PAGE_WRITE);
142 131
@@ -152,5 +141,5 @@ inline void sh64_setup_tlb_slot(unsigned long long config_addr,
152 * 141 *
153 * Teardown any existing mapping in the TLB slot @config_addr. 142 * Teardown any existing mapping in the TLB slot @config_addr.
154 */ 143 */
155inline void sh64_teardown_tlb_slot(unsigned long long config_addr) 144void sh64_teardown_tlb_slot(unsigned long long config_addr)
156 __attribute__ ((alias("__flush_tlb_slot"))); 145 __attribute__ ((alias("__flush_tlb_slot")));
diff --git a/arch/sh/mm/tlbflush_64.c b/arch/sh/mm/tlbflush_64.c
index f2e44e9ffb75..fa5a95a062d0 100644
--- a/arch/sh/mm/tlbflush_64.c
+++ b/arch/sh/mm/tlbflush_64.c
@@ -337,7 +337,7 @@ void local_flush_tlb_one(unsigned long asid, unsigned long page)
337 /* 337 /*
338 * Sign-extend based on neff. 338 * Sign-extend based on neff.
339 */ 339 */
340 lpage = (page & NEFF_SIGN) ? (page | NEFF_MASK) : page; 340 lpage = neff_sign_extend(page);
341 match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID; 341 match = (asid << PTEH_ASID_SHIFT) | PTEH_VALID;
342 match |= lpage; 342 match |= lpage;
343 343