From: Sam Ravnborg <sam@xxxxxxxxxxxx> Some older SPARC CPUs had support for only 7 register windows. To support this run-time patching was used. LEON demand 8 register windows for use with Linux so there is no need to support the 7 window configuration. The complexity of the assembler code is reduced when dropping the run-time patching, thus increasing the maintainability. Signed-off-by: Sam Ravnborg <sam@xxxxxxxxxxxx> Cc: Sam Ravnborg <sam@xxxxxxxxxxxx> Cc: "David S. Miller" <davem@xxxxxxxxxxxxx> Cc: Andreas Larsson <andreas@xxxxxxxxxxx> --- arch/sparc/include/asm/switch_to_32.h | 1 - arch/sparc/kernel/entry.S | 28 ++++----------- arch/sparc/kernel/etrap_32.S | 35 +++++-------------- arch/sparc/kernel/head_32.S | 65 ----------------------------------- arch/sparc/kernel/rtrap_32.S | 55 +++++++++++++---------------- arch/sparc/kernel/wof.S | 43 ++++++++--------------- arch/sparc/kernel/wuf.S | 20 +++-------- 7 files changed, 57 insertions(+), 190 deletions(-) diff --git a/arch/sparc/include/asm/switch_to_32.h b/arch/sparc/include/asm/switch_to_32.h index 42eeafcb8a41..7aaaf31c09b4 100644 --- a/arch/sparc/include/asm/switch_to_32.h +++ b/arch/sparc/include/asm/switch_to_32.h @@ -37,7 +37,6 @@ extern struct thread_info *current_set[NR_CPUS]; #define prepare_arch_switch(next) do { \ __asm__ __volatile__( \ - ".globl\tflush_patch_switch\nflush_patch_switch:\n\t" \ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ "save %sp, -0x40, %sp; save %sp, -0x40, %sp; save %sp, -0x40, %sp\n\t" \ "save %sp, -0x40, %sp\n\t" \ diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index 9cf8f87e8c42..078a8f7f8383 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -384,11 +384,8 @@ do_flush_windows: RESTORE_ALL - .globl flush_patch_one - /* We get these for debugging routines using __builtin_return_address() */ dfw_kernel: -flush_patch_one: FLUSH_ALL_KERNEL_WINDOWS /* Advance over the trap instruction. */ @@ -558,10 +555,9 @@ sys_rt_sigreturn: * XXX code just like on sparc64... -DaveM */ .align 4 - .globl sys_fork, flush_patch_two + .globl sys_fork sys_fork: mov %o7, %l5 -flush_patch_two: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -574,10 +570,9 @@ flush_patch_two: mov %l5, %o7 /* Whee, kernel threads! */ - .globl sys_clone, flush_patch_three + .globl sys_clone sys_clone: mov %o7, %l5 -flush_patch_three: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -590,9 +585,8 @@ flush_patch_three: mov %l5, %o7 /* Whee, real vfork! */ - .globl sys_vfork, flush_patch_four + .globl sys_vfork sys_vfork: -flush_patch_four: FLUSH_ALL_KERNEL_WINDOWS; ld [%curptr + TI_TASK], %o4 rd %psr, %g4 @@ -909,17 +903,7 @@ breakpoint_trap: #endif .align 4 - .globl flush_patch_exception -flush_patch_exception: - FLUSH_ALL_KERNEL_WINDOWS; - ldd [%o0], %o6 - jmpl %o7 + 0xc, %g0 ! see asm-sparc/processor.h - mov 1, %g1 ! signal EFAULT condition - - .align 4 - .globl kill_user_windows, kuw_patch1_7win - .globl kuw_patch1 -kuw_patch1_7win: sll %o3, 6, %o3 + .globl kill_user_windows /* No matter how much overhead this routine has in the worst * case scenario, it is several times better than taking the @@ -939,11 +923,11 @@ kill_user_windows: be 4f ! yep, we are done rd %wim, %o3 ! get current wim srl %o3, 1, %o4 ! simulate a save -kuw_patch1: +kuw_next: sll %o3, 7, %o3 ! compute next wim or %o4, %o3, %o3 ! result andncc %o0, %o3, %o0 ! clean this bit in umask - bne kuw_patch1 ! not done yet + bne kuw_next ! not done yet srl %o3, 1, %o4 ! begin another save simulation wr %o3, 0x0, %wim ! set the new wim st %g0, [%g6 + TI_UWINMASK] ! clear uwinmask diff --git a/arch/sparc/kernel/etrap_32.S b/arch/sparc/kernel/etrap_32.S index bb222459f097..95dfdea1f36c 100644 --- a/arch/sparc/kernel/etrap_32.S +++ b/arch/sparc/kernel/etrap_32.S @@ -30,18 +30,6 @@ .text .align 4 - /* SEVEN WINDOW PATCH INSTRUCTIONS */ - .globl tsetup_7win_patch1, tsetup_7win_patch2 - .globl tsetup_7win_patch3, tsetup_7win_patch4 - .globl tsetup_7win_patch5, tsetup_7win_patch6 -tsetup_7win_patch1: sll %t_wim, 0x6, %t_wim -tsetup_7win_patch2: and %g2, 0x7f, %g2 -tsetup_7win_patch3: and %g2, 0x7f, %g2 -tsetup_7win_patch4: and %g1, 0x7f, %g1 -tsetup_7win_patch5: sll %t_wim, 0x6, %t_wim -tsetup_7win_patch6: and %g2, 0x7f, %g2 - /* END OF PATCH INSTRUCTIONS */ - /* At trap time, interrupts and all generic traps do the * following: * @@ -72,9 +60,7 @@ tsetup_7win_patch6: and %g2, 0x7f, %g2 * trap pc and npc, and %l3 contains the trap time %wim. */ - .globl trap_setup, tsetup_patch1, tsetup_patch2 - .globl tsetup_patch3, tsetup_patch4 - .globl tsetup_patch5, tsetup_patch6 + .globl trap_setup trap_setup: /* Calculate mask of trap window. See if from user * or kernel and branch conditionally. @@ -109,11 +95,10 @@ trap_setup_kernel_spill: * %wim and go. */ srl %t_wim, 0x1, %g2 ! begin computation of new %wim -tsetup_patch1: - sll %t_wim, 0x7, %t_wim ! patched on 7 window Sparcs + + sll %t_wim, 0x7, %t_wim or %t_wim, %g2, %g2 -tsetup_patch2: - and %g2, 0xff, %g2 ! patched on 7 window Sparcs + and %g2, 0xff, %g2 save %g0, %g0, %g0 @@ -185,8 +170,7 @@ trap_setup_from_user: sub %g2, 0x1, %g2 1: andn %g2, %t_twinmask, %g2 -tsetup_patch3: - and %g2, 0xff, %g2 ! patched on 7win Sparcs + and %g2, 0xff, %g2 st %g2, [%curptr + TI_UWINMASK] ! store new umask jmpl %t_retpc + 0x8, %g0 ! return to caller @@ -199,14 +183,11 @@ trap_setup_user_spill: * is in %g1 upon entry to here. */ -tsetup_patch4: - and %g1, 0xff, %g1 ! patched on 7win Sparcs, mask + and %g1, 0xff, %g1 srl %t_wim, 0x1, %g2 ! compute new %wim -tsetup_patch5: - sll %t_wim, 0x7, %t_wim ! patched on 7win Sparcs + sll %t_wim, 0x7, %t_wim or %t_wim, %g2, %g2 ! %g2 is new %wim -tsetup_patch6: - and %g2, 0xff, %g2 ! patched on 7win Sparcs + and %g2, 0xff, %g2 andn %g1, %g2, %g1 ! clear this bit in %g1 st %g1, [%curptr + TI_UWINMASK] diff --git a/arch/sparc/kernel/head_32.S b/arch/sparc/kernel/head_32.S index 03dc232dd235..908c77cb456e 100644 --- a/arch/sparc/kernel/head_32.S +++ b/arch/sparc/kernel/head_32.S @@ -404,71 +404,6 @@ leon_init: wr %g1, 0x0, %wim ! make window 1 invalid WRITE_PAUSE - cmp %g3, 0x7 - bne 2f - nop - - /* Adjust our window handling routines to - * do things correctly on 7 window Sparcs. - */ - -#define PATCH_INSN(src, dest) \ - set src, %g5; \ - set dest, %g2; \ - ld [%g5], %g4; \ - st %g4, [%g2]; - - /* Patch for window spills... */ - PATCH_INSN(spnwin_patch1_7win, spnwin_patch1) - PATCH_INSN(spnwin_patch2_7win, spnwin_patch2) - PATCH_INSN(spnwin_patch3_7win, spnwin_patch3) - - /* Patch for window fills... */ - PATCH_INSN(fnwin_patch1_7win, fnwin_patch1) - PATCH_INSN(fnwin_patch2_7win, fnwin_patch2) - - /* Patch for trap entry setup... */ - PATCH_INSN(tsetup_7win_patch1, tsetup_patch1) - PATCH_INSN(tsetup_7win_patch2, tsetup_patch2) - PATCH_INSN(tsetup_7win_patch3, tsetup_patch3) - PATCH_INSN(tsetup_7win_patch4, tsetup_patch4) - PATCH_INSN(tsetup_7win_patch5, tsetup_patch5) - PATCH_INSN(tsetup_7win_patch6, tsetup_patch6) - - /* Patch for returning from traps... */ - PATCH_INSN(rtrap_7win_patch1, rtrap_patch1) - PATCH_INSN(rtrap_7win_patch2, rtrap_patch2) - PATCH_INSN(rtrap_7win_patch3, rtrap_patch3) - PATCH_INSN(rtrap_7win_patch4, rtrap_patch4) - PATCH_INSN(rtrap_7win_patch5, rtrap_patch5) - - /* Patch for killing user windows from the register file. */ - PATCH_INSN(kuw_patch1_7win, kuw_patch1) - - /* Now patch the kernel window flush sequences. - * This saves 2 traps on every switch and fork. - */ - set 0x01000000, %g4 - set flush_patch_one, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - set flush_patch_two, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - set flush_patch_three, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - set flush_patch_four, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - set flush_patch_exception, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - set flush_patch_switch, %g5 - st %g4, [%g5 + 0x18] - st %g4, [%g5 + 0x1c] - -2: sethi %hi(nwindows), %g4 st %g3, [%g4 + %lo(nwindows)] ! store final value sub %g3, 0x1, %g3 diff --git a/arch/sparc/kernel/rtrap_32.S b/arch/sparc/kernel/rtrap_32.S index a232b367c219..8383048c3b5e 100644 --- a/arch/sparc/kernel/rtrap_32.S +++ b/arch/sparc/kernel/rtrap_32.S @@ -23,15 +23,6 @@ #define glob_tmp g4 #define curptr g6 - /* 7 WINDOW SPARC PATCH INSTRUCTIONS */ - .globl rtrap_7win_patch1, rtrap_7win_patch2, rtrap_7win_patch3 - .globl rtrap_7win_patch4, rtrap_7win_patch5 -rtrap_7win_patch1: srl %t_wim, 0x6, %glob_tmp -rtrap_7win_patch2: and %glob_tmp, 0x7f, %glob_tmp -rtrap_7win_patch3: srl %g1, 7, %g2 -rtrap_7win_patch4: srl %g2, 6, %g2 -rtrap_7win_patch5: and %g1, 0x7f, %g1 - /* END OF PATCH INSTRUCTIONS */ /* We need to check for a few things which are: * 1) The need to call schedule() because this @@ -117,17 +108,17 @@ ret_trap_nobufwins: bne ret_trap_userwins_ok nop - /* Calculate new %wim, we have to pull a register - * window from the users stack. - */ + /* Calculate new %wim, we have to pull a register + * window from the users stack. + */ ret_trap_pull_one_window: - rd %wim, %t_wim - sll %t_wim, 0x1, %twin_tmp1 -rtrap_patch1: srl %t_wim, 0x7, %glob_tmp - or %glob_tmp, %twin_tmp1, %glob_tmp -rtrap_patch2: and %glob_tmp, 0xff, %glob_tmp + rd %wim, %t_wim + sll %t_wim, 0x1, %twin_tmp1 + srl %t_wim, 0x7, %glob_tmp + or %glob_tmp, %twin_tmp1, %glob_tmp + and %glob_tmp, 0xff, %glob_tmp - wr %glob_tmp, 0x0, %wim + wr %glob_tmp, 0x0, %wim /* Here comes the architecture specific * branch to the user stack checking routine @@ -174,20 +165,20 @@ ret_trap_unaligned_pc: ld [%curptr + TI_FLAGS], %g2 ret_trap_kernel: - /* Will the rett land us in the invalid window? */ - mov 2, %g1 - sll %g1, %t_psr, %g1 -rtrap_patch3: srl %g1, 8, %g2 - or %g1, %g2, %g1 - rd %wim, %g2 - andcc %g2, %g1, %g0 - be 1f ! Nope, just return from the trap - sll %g2, 0x1, %g1 - - /* We have to grab a window before returning. */ -rtrap_patch4: srl %g2, 7, %g2 - or %g1, %g2, %g1 -rtrap_patch5: and %g1, 0xff, %g1 + /* Will the rett land us in the invalid window? */ + mov 2, %g1 + sll %g1, %t_psr, %g1 + srl %g1, 8, %g2 + or %g1, %g2, %g1 + rd %wim, %g2 + andcc %g2, %g1, %g0 + be 1f ! Nope, just return from the trap + sll %g2, 0x1, %g1 + + /* We have to grab a window before returning. */ + srl %g2, 7, %g2 + or %g1, %g2, %g1 + and %g1, 0xff, %g1 wr %g1, 0x0, %wim diff --git a/arch/sparc/kernel/wof.S b/arch/sparc/kernel/wof.S index fe4cfd4abcd2..30c5ebdd035c 100644 --- a/arch/sparc/kernel/wof.S +++ b/arch/sparc/kernel/wof.S @@ -43,18 +43,6 @@ #define twin_tmp l4 /* Temp reg, only usable in trap window T */ #define glob_tmp g5 /* Global temporary reg, usable anywhere G */ - .text - .align 4 - /* BEGINNING OF PATCH INSTRUCTIONS */ - /* On a 7-window Sparc the boot code patches spnwin_* - * instructions with the following ones. - */ - .globl spnwin_patch1_7win, spnwin_patch2_7win, spnwin_patch3_7win -spnwin_patch1_7win: sll %t_wim, 6, %glob_tmp -spnwin_patch2_7win: and %glob_tmp, 0x7f, %glob_tmp -spnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp - /* END OF PATCH INSTRUCTIONS */ - /* The trap entry point has done the following: * * rd %psr, %l0 @@ -69,7 +57,6 @@ spnwin_patch3_7win: and %twin_tmp, 0x7f, %twin_tmp * will be all zeroes. */ .globl spill_window_entry - .globl spnwin_patch1, spnwin_patch2, spnwin_patch3 spill_window_entry: /* LOCATION: Trap Window */ @@ -81,10 +68,10 @@ spill_window_entry: * * newwim = ((%wim>>1) | (%wim<<(nwindows - 1))); */ - srl %t_wim, 0x1, %twin_tmp -spnwin_patch1: sll %t_wim, 7, %glob_tmp - or %glob_tmp, %twin_tmp, %glob_tmp -spnwin_patch2: and %glob_tmp, 0xff, %glob_tmp + srl %t_wim, 0x1, %twin_tmp + sll %t_wim, 7, %glob_tmp + or %glob_tmp, %twin_tmp, %glob_tmp + and %glob_tmp, 0xff, %glob_tmp /* The trap entry point has set the condition codes * up for us to see if this is from user or kernel. @@ -222,17 +209,17 @@ spwin_user_stack_is_bolixed: mov 1, %twin_tmp st %twin_tmp, [%curptr + TI_W_SAVED] - /* Compute new user window mask. What we are basically - * doing is taking two windows, the invalid one at trap - * time and the one we attempted to throw onto the users - * stack, and saying that everything else is an ok user - * window. umask = ((~(%t_wim | %wim)) & valid_wim_bits) - */ - rd %wim, %twin_tmp - or %twin_tmp, %t_wim, %twin_tmp - not %twin_tmp -spnwin_patch3: and %twin_tmp, 0xff, %twin_tmp ! patched on 7win Sparcs - st %twin_tmp, [%curptr + TI_UWINMASK] + /* Compute new user window mask. What we are basically + * doing is taking two windows, the invalid one at trap + * time and the one we attempted to throw onto the users + * stack, and saying that everything else is an ok user + * window. umask = ((~(%t_wim | %wim)) & valid_wim_bits) + */ + rd %wim, %twin_tmp + or %twin_tmp, %t_wim, %twin_tmp + not %twin_tmp + and %twin_tmp, 0xff, %twin_tmp + st %twin_tmp, [%curptr + TI_UWINMASK] #define STACK_OFFSET (THREAD_SIZE - TRACEREG_SZ - STACKFRAME_SZ) diff --git a/arch/sparc/kernel/wuf.S b/arch/sparc/kernel/wuf.S index 4c52b69d4b7a..dd2a539f92ff 100644 --- a/arch/sparc/kernel/wuf.S +++ b/arch/sparc/kernel/wuf.S @@ -68,27 +68,17 @@ * are done and return from trap if successful */ - /* BEGINNING OF PATCH INSTRUCTIONS */ - - /* On 7-window Sparc the boot code patches fnwin_patch1 - * with the following instruction. - */ - .globl fnwin_patch1_7win, fnwin_patch2_7win -fnwin_patch1_7win: srl %t_wim, 6, %twin_tmp2 -fnwin_patch2_7win: and %twin_tmp1, 0x7f, %twin_tmp1 - /* END OF PATCH INSTRUCTIONS */ - - .globl fill_window_entry, fnwin_patch1, fnwin_patch2 + .globl fill_window_entry fill_window_entry: /* LOCATION: Window 'T' */ /* Compute what the new %wim is going to be if we retrieve * the proper window off of the stack. */ - sll %t_wim, 1, %twin_tmp1 -fnwin_patch1: srl %t_wim, 7, %twin_tmp2 - or %twin_tmp1, %twin_tmp2, %twin_tmp1 -fnwin_patch2: and %twin_tmp1, 0xff, %twin_tmp1 + sll %t_wim, 1, %twin_tmp1 + srl %t_wim, 7, %twin_tmp2 + or %twin_tmp1, %twin_tmp2, %twin_tmp1 + and %twin_tmp1, 0xff, %twin_tmp1 wr %twin_tmp1, 0x0, %wim /* Make window 'I' invalid */ -- 2.34.1