📄 entry.s
字号:
wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call handle_reg_access mov %l0, %o3 RESTORE_ALL /* This routine handles Co-Processor Disabled Exceptions. */ .align 4 .globl do_cp_disableddo_cp_disabled: SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call handle_cp_disabled mov %l0, %o3 RESTORE_ALL /* This routine handles Co-Processor Exceptions. */ .align 4 .globl do_cp_exceptiondo_cp_exception: SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call handle_cp_exception mov %l0, %o3 RESTORE_ALL /* This routine handles Hardware Divide By Zero Exceptions. */ .align 4 .globl do_hw_divzerodo_hw_divzero: SAVE_ALL wr %l0, PSR_ET, %psr ! re-enable traps WRITE_PAUSE add %sp, STACKFRAME_SZ, %o0 mov %l1, %o1 mov %l2, %o2 call handle_hw_divzero mov %l0, %o3 RESTORE_ALL .align 4 .globl do_flush_windowsdo_flush_windows: SAVE_ALL wr %l0, PSR_ET, %psr WRITE_PAUSE andcc %l0, PSR_PS, %g0 bne dfw_kernel nop call flush_user_windows nop /* Advance over the trap instruction. */ ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 add %l1, 0x4, %l2 st %l1, [%sp + STACKFRAME_SZ + PT_PC] st %l2, [%sp + STACKFRAME_SZ + PT_NPC] 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. */ ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 add %l1, 0x4, %l2 st %l1, [%sp + STACKFRAME_SZ + PT_PC] st %l2, [%sp + STACKFRAME_SZ + PT_NPC] RESTORE_ALL /* The getcc software trap. The user wants the condition codes from * the %psr in register %g1. */ .align 4 .globl getcc_trap_handlergetcc_trap_handler: srl %l0, 20, %g1 ! give user and %g1, 0xf, %g1 ! only ICC bits in %psr jmp %l2 ! advance over trap instruction rett %l2 + 0x4 ! like this... /* The setcc software trap. The user has condition codes in %g1 * that it would like placed in the %psr. Be careful not to flip * any unintentional bits! */ .align 4 .globl setcc_trap_handlersetcc_trap_handler: sll %g1, 0x14, %l4 set PSR_ICC, %l5 andn %l0, %l5, %l0 ! clear ICC bits in %psr and %l4, %l5, %l4 ! clear non-ICC bits in user value or %l4, %l0, %l4 ! or them in... mix mix mix wr %l4, 0x0, %psr ! set new %psr WRITE_PAUSE ! TI scumbags... jmp %l2 ! advance over trap instruction rett %l2 + 0x4 ! like this... .align 4 .globl linux_trap_nmi_sun4clinux_trap_nmi_sun4c: SAVE_ALL /* Ugh, we need to clear the IRQ line. This is now * a very sun4c specific trap handler... */ sethi %hi(interrupt_enable), %l5 ld [%l5 + %lo(interrupt_enable)], %l5 ldub [%l5], %l6 andn %l6, INTS_ENAB, %l6 stb %l6, [%l5] /* Now it is safe to re-enable traps without recursion. */ or %l0, PSR_PIL, %l0 wr %l0, PSR_ET, %psr WRITE_PAUSE /* Now call the c-code with the pt_regs frame ptr and the * memory error registers as arguments. The ordering chosen * here is due to unlatching semantics. */ sethi %hi(AC_SYNC_ERR), %o0 add %o0, 0x4, %o0 lda [%o0] ASI_CONTROL, %o2 ! sync vaddr sub %o0, 0x4, %o0 lda [%o0] ASI_CONTROL, %o1 ! sync error add %o0, 0xc, %o0 lda [%o0] ASI_CONTROL, %o4 ! async vaddr sub %o0, 0x4, %o0 lda [%o0] ASI_CONTROL, %o3 ! async error call sparc_lvl15_nmi add %sp, STACKFRAME_SZ, %o0 RESTORE_ALL .align 4 .globl invalid_segment_patch1_ff .globl invalid_segment_patch2_ffinvalid_segment_patch1_ff: cmp %l4, 0xffinvalid_segment_patch2_ff: mov 0xff, %l3 .align 4 .globl invalid_segment_patch1_1ff .globl invalid_segment_patch2_1ffinvalid_segment_patch1_1ff: cmp %l4, 0x1ffinvalid_segment_patch2_1ff: mov 0x1ff, %l3 .align 4 .globl num_context_patch1_16, num_context_patch2_16num_context_patch1_16: mov 0x10, %l7num_context_patch2_16: mov 0x10, %l7 .align 4 .globl vac_linesize_patch_32vac_linesize_patch_32: subcc %l7, 32, %l7 .align 4 .globl vac_hwflush_patch1_on, vac_hwflush_patch2_on/* * Ugly, but we cant use hardware flushing on the sun4 and we'd require * two instructions (Anton) */#ifdef CONFIG_SUN4vac_hwflush_patch1_on: nop#elsevac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7#endifvac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG .globl invalid_segment_patch1, invalid_segment_patch2 .globl num_context_patch1, num_context_patch2 .globl vac_linesize_patch, vac_hwflush_patch1 .globl vac_hwflush_patch2 .align 4 .globl sun4c_fault! %l0 = %psr! %l1 = %pc! %l2 = %npc! %l3 = %wim! %l7 = 1 for textfault! We want error in %l5, vaddr in %l6sun4c_fault:#ifdef CONFIG_SUN4 sethi %hi(sun4c_memerr_reg), %l4 ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr ld [%l4], %l6 ! memerr ctrl reg ld [%l4 + 4], %l5 ! memerr vaddr reg andcc %l6, 0x80, %g0 ! check for error type st %g0, [%l4 + 4] ! clear the error be 0f ! normal error sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr call prom_halt ! something weird happened ! what exactly did happen? ! what should we do here?0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr lduba [%l4] ASI_CONTROL, %l6 ! bus err reg cmp %l7, 1 ! text fault? be 1f ! yes nop ld [%l1], %l4 ! load instruction that caused fault srl %l4, 21, %l4 andcc %l4, 1, %g0 ! store instruction? be 1f ! no sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep ! %lo(SUN4C_SYNC_BADWRITE) = 0 or %l4, %l6, %l6 ! set write bit to emulate sun4c1:#else sethi %hi(AC_SYNC_ERR), %l4 add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 lda [%l6] ASI_CONTROL, %l5 ! Address lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit#endif andn %l5, 0xfff, %l5 ! Encode all info into l7 srl %l6, 14, %l4 and %l4, 2, %l4 or %l5, %l4, %l4 or %l4, %l7, %l7 ! l7 = [addr,write,txtfault] andcc %l0, PSR_PS, %g0 be sun4c_fault_fromuser andcc %l7, 1, %g0 ! Text fault? be 1f sethi %hi(KERNBASE), %l4 mov %l1, %l5 ! PC1: cmp %l5, %l4 blu sun4c_fault_fromuser sethi %hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4 /* If the kernel references a bum kernel pointer, or a pte which * points to a non existant page in ram, we will run this code * _forever_ and lock up the machine!!!!! So we must check for * this condition, the AC_SYNC_ERR bits are what we must examine. * Also a parity error would make this happen as well. So we just * check that we are in fact servicing a tlb miss and not some * other type of fault for the kernel. */ andcc %l6, 0x80, %g0 be sun4c_fault_fromuser and %l5, %l4, %l5 /* Test for NULL pte_t * in vmalloc area. */ sethi %hi(VMALLOC_START), %l4 cmp %l5, %l4 blu,a invalid_segment_patch1 lduXa [%l5] ASI_SEGMAP, %l4 sethi %hi(swapper_pg_dir), %l4 srl %l5, SUN4C_PGDIR_SHIFT, %l6 or %l4, %lo(swapper_pg_dir), %l4 sll %l6, 2, %l6 ld [%l4 + %l6], %l4#ifdef CONFIG_SUN4 sethi %hi(PAGE_MASK), %l6 andcc %l4, %l6, %g0#else andcc %l4, PAGE_MASK, %g0#endif be sun4c_fault_fromuser lduXa [%l5] ASI_SEGMAP, %l4invalid_segment_patch1: cmp %l4, 0x7f bne 1f sethi %hi(sun4c_kfree_ring), %l4 or %l4, %lo(sun4c_kfree_ring), %l4 ld [%l4 + 0x18], %l3 deccc %l3 ! do we have a free entry? bcs,a 2f ! no, unmap one. sethi %hi(sun4c_kernel_ring), %l4 st %l3, [%l4 + 0x18] ! sun4c_kfree_ring.num_entries-- ld [%l4 + 0x00], %l6 ! entry = sun4c_kfree_ring.ringhd.next st %l5, [%l6 + 0x08] ! entry->vaddr = address ld [%l6 + 0x00], %l3 ! next = entry->next ld [%l6 + 0x04], %l7 ! entry->prev st %l7, [%l3 + 0x04] ! next->prev = entry->prev st %l3, [%l7 + 0x00] ! entry->prev->next = next sethi %hi(sun4c_kernel_ring), %l4 or %l4, %lo(sun4c_kernel_ring), %l4 ! head = &sun4c_kernel_ring.ringhd ld [%l4 + 0x00], %l7 ! head->next st %l4, [%l6 + 0x04] ! entry->prev = head st %l7, [%l6 + 0x00] ! entry->next = head->next st %l6, [%l7 + 0x04] ! head->next->prev = entry st %l6, [%l4 + 0x00] ! head->next = entry ld [%l4 + 0x18], %l3 inc %l3 ! sun4c_kernel_ring.num_entries++ st %l3, [%l4 + 0x18] b 4f ld [%l6 + 0x08], %l52: or %l4, %lo(sun4c_kernel_ring), %l4 ! head = &sun4c_kernel_ring.ringhd ld [%l4 + 0x04], %l6 ! entry = head->prev ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr ! Flush segment from the cache.#ifdef CONFIG_SUN4 sethi %hi((128 * 1024)), %l7#else sethi %hi((64 * 1024)), %l7#endif9:vac_hwflush_patch1:vac_linesize_patch: subcc %l7, 16, %l7 bne 9bvac_hwflush_patch2: sta %g0, [%l3 + %l7] ASI_FLUSHSEG st %l5, [%l6 + 0x08] ! entry->vaddr = address ld [%l6 + 0x00], %l5 ! next = entry->next ld [%l6 + 0x04], %l7 ! entry->prev st %l7, [%l5 + 0x04] ! next->prev = entry->prev st %l5, [%l7 + 0x00] ! entry->prev->next = next st %l4, [%l6 + 0x04] ! entry->prev = head ld [%l4 + 0x00], %l7 ! head->next st %l7, [%l6 + 0x00] ! entry->next = head->next st %l6, [%l7 + 0x04] ! head->next->prev = entry st %l6, [%l4 + 0x00] ! head->next = entry mov %l3, %l5 ! address = tmp4:num_context_patch1: mov 0x08, %l7 ld [%l6 + 0x08], %l4 ldub [%l6 + 0x0c], %l3 or %l4, %l3, %l4 ! encode new vaddr/pseg into l4 sethi %hi(AC_CONTEXT), %l3 lduba [%l3] ASI_CONTROL, %l6 /* Invalidate old mapping, instantiate new mapping, * for each context. Registers l6/l7 are live across * this loop. */3: deccc %l7 sethi %hi(AC_CONTEXT), %l3 stba %l7, [%l3] ASI_CONTROLinvalid_segment_patch2: mov 0x7f, %l3 stXa %l3, [%l5] ASI_SEGMAP andn %l4, 0x1ff, %l3 bne 3b stXa %l4, [%l3] ASI_SEGMAP sethi %hi(AC_CONTEXT), %l3 stba %l6, [%l3] ASI_CONTROL andn %l4, 0x1ff, %l51: sethi %hi(VMALLOC_START), %l4 cmp %l5, %l4 bgeu 1f mov 1 << (SUN4C_REAL_PGDIR_SHIFT - PAGE_SHIFT), %l7 sethi %hi(KERNBASE), %l6 sub %l5, %l6, %l4 srl %l4, PAGE_SHIFT, %l4 sethi %hi((SUN4C_PAGE_KERNEL & 0xf4000000)), %l3 or %l3, %l4, %l3 sethi %hi(PAGE_SIZE), %l42: sta %l3, [%l5] ASI_PTE deccc %l7 inc %l3 bne 2b add %l5, %l4, %l5 b 7f sethi %hi(sun4c_kernel_faults), %l41: srl %l5, SUN4C_PGDIR_SHIFT, %l3 sethi %hi(swapper_pg_dir), %l4 or %l4, %lo(swapper_pg_dir), %l4 sll %l3, 2, %l3 ld [%l4 + %l3], %l4#ifndef CONFIG_SUN4 and %l4, PAGE_MASK, %l4#else sethi %hi(PAGE_MASK), %l6 and %l4, %l6, %l4#endif srl %l5, (PAGE_SHIFT - 2), %l6 and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 add %l6, %l4, %l6 sethi %hi(PAGE_SIZE), %l42: ld [%l6], %l3 deccc %l7 sta %l3, [%l5] ASI_PTE add %l6, 0x4, %l6 bne 2b add %l5, %l4, %l5 sethi %hi(sun4c_kernel_faults), %l47: ld [%l4 + %lo(sun4c_kernel_faults)], %l3 inc %l3 st %l3, [%l4 + %lo(sun4c_kernel_faults)] /* Restore condition codes */ wr %l0, 0x0, %psr WRITE_PAUSE jmp %l1 rett %l2sun4c_fault_fromuser: SAVE_ALL nop mov %l7, %o1 ! Decode the info from %l7 mov %l7, %o2 and %o1, 1, %o1 ! arg2 = text_faultp mov %l7, %o3 and %o2, 2, %o2 ! arg3 = writep andn %o3, 0xfff, %o3 ! arg4 = faulting address wr %l0, PSR_ET, %psr WRITE_PAUSE call do_sun4c_fault add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr RESTORE_ALL .align 4 .globl srmmu_faultsrmmu_fault: mov 0x400, %l5 mov 0x300, %l4 lda [%l5] ASI_M_MMUREGS, %l6 ! read sfar first lda [%l4] ASI_M_MMUREGS, %l5 ! read sfsr last andn %l6, 0xfff, %l6 srl %l5, 6, %l5 ! and encode all info into l7 and %l5, 2, %l5 or %l5, %l6, %l6 or %l6, %l7, %l7 ! l7 = [addr,write,txtfault] SAVE_ALL mov %l7, %o1 mov %l7, %o2 and %o1, 1, %o1 ! arg2 = text_faultp mov %l7, %o3 and %o2, 2, %o2 ! arg3 = writep andn %o3, 0xfff, %o3 ! arg4 = faulting address wr %l0, PSR_ET, %psr WRITE_PAUSE call do_sparc_fault add %sp, STACKFRAME_SZ, %o0 ! arg1 = pt_regs ptr RESTORE_ALL#ifdef CONFIG_SUNOS_EMUL /* SunOS uses syscall zero as the 'indirect syscall' it looks * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. * This is complete brain damage. */ .globl sunos_indirsunos_indir: mov %o7, %l4 cmp %o0, NR_SYSCALLS blu,a 1f sll %o0, 0x2, %o0 sethi %hi(sunos_nosys), %l6 b 2f or %l6, %lo(sunos_nosys), %l61: set sunos_sys_table, %l7 ld [%l7 + %o0], %l62: mov %o1, %o0 mov %o2, %o1 mov %o3, %o2 mov %o4, %o3 mov %o5, %o4 call %l6 mov %l4, %o7#endif .align 4 .globl sys_nis_syscallsys_nis_syscall: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg call c_sys_nis_syscall mov %l5, %o7 .align 4 .globl sys_ptracesys_ptrace: call do_ptrace add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop call syscall_trace nop1: RESTORE_ALL .align 4 .globl sys_execvesys_execve: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg call sparc_execve mov %l5, %o7 .align 4 .globl sys_pipesys_pipe: mov %o7, %l5 add %sp, STACKFRAME_SZ, %o0 ! pt_regs *regs arg call sparc_pipe mov %l5, %o7 .align 4 .globl sys_sigaltstacksys_sigaltstack: mov %o7, %l5 mov %fp, %o2 call do_sigaltstack mov %l5, %o7 .align 4 .globl sys_sigstacksys_sigstack: mov %o7, %l5 mov %fp, %o2 call do_sys_sigstack mov %l5, %o7 .align 4 .globl sys_sigpausesys_sigpause: /* Note: %o0 already has correct value... */ call do_sigpause add %sp, STACKFRAME_SZ, %o1 ld [%curptr + TI_FLAGS], %l5 andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f nop call syscall_trace nop1: /* We are returning to a signal handler. */ RESTORE_ALL .align 4 .globl sys_sigsuspendsys_sigsuspend: call do_sigsuspend add %sp, STACKFRAME_SZ, %o0 ld [%curptr + TI_FLAGS], %l5 andcc %l5, _TIF_SYSCALL_TRACE, %g0 be 1f
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -