📄 misc.s
字号:
/* * arch/ppc/kernel/misc.S * * * * This file contains miscellaneous low-level functions. * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * * Largely rewritten by Cort Dougan (cort@cs.nmt.edu) * and Paul Mackerras. * Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com) * PPC64 updates by Dave Engebretsen (engebret@us.ibm.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */#include <linux/config.h>#include <linux/sys.h>#include <asm/unistd.h>#include <asm/errno.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/cache.h>#include "ppc_asm.h" .text/* * Returns (address we're running at) - (address we were linked at) * for use before the text and data are mapped to KERNELBASE. */_GLOBAL(reloc_offset) mflr r0 bl 1f1: mflr r3 LOADADDR(r4,1b) sub r3,r4,r3 mtlr r0 blr_GLOBAL(get_msr) mfmsr r3 blr_GLOBAL(get_dar) mfdar r3 blr_GLOBAL(get_srr0) mfsrr0 r3 blr_GLOBAL(get_srr1) mfsrr1 r3 blr _GLOBAL(get_sp) mr r3,r1 blr #ifdef CONFIG_PPC_ISERIES/* unsigned long __no_use_save_flags(void) */_GLOBAL(__no_use_save_flags) mfspr r4,SPRG3 lbz r3,PACAPROCENABLED(r4) blr/* void __no_use_restore_flags(unsigned long flags) */ _GLOBAL(__no_use_restore_flags)/* * Just set/clear the MSR_EE bit through restore/flags but do not * change anything else. This is needed by the RT system and makes * sense anyway. * -- Cort */ mfspr r6,SPRG3 lbz r5,PACAPROCENABLED(r6) /* Check if things are setup the way we want _already_. */ cmpw 0,r3,r5 beqlr /* are we enabling interrupts? */ cmpi 0,r3,0 stb r3,PACAPROCENABLED(r6) beqlr /* Check pending interrupts */ CHECKANYINT(r4,r5) beqlr /* * Handle pending interrupts in interrupt context */ li r0,0x5555 sc blr_GLOBAL(__no_use_cli) mfspr r5,SPRG3 lbz r3,PACAPROCENABLED(r5) li r4,0 stb r4,PACAPROCENABLED(r5) blr /* Done */_GLOBAL(__no_use_sti) mfspr r6,SPRG3 li r3,1 stb r3,PACAPROCENABLED(r6) /* Check for pending interrupts * A decrementer, IPI or PMC interrupt may have occurred * while we were in the hypervisor (which enables) */ CHECKANYINT(r4,r5) beqlr /* * Handle pending interrupts in interrupt context */ li r0,0x5555 sc blr#endif/* * Flush instruction cache. */_GLOBAL(flush_instruction_cache)/* * This is called by kgdb code * and should probably go away * to be replaced by invalidating * the cache lines that are actually * modified */ /* use invalidate-all bit in HID0 * - is this consistent across all 64-bit cpus? -- paulus */ mfspr r3,HID0 ori r3,r3,HID0_ICFI mtspr HID0,r3 sync isync blr/* * Write any modified data cache blocks out to memory * and invalidate the corresponding instruction cache blocks. * * flush_icache_range(unsigned long start, unsigned long stop) * * flush all bytes from start through stop-1 inclusive */_GLOBAL(flush_icache_range)/* * Flush the data cache to memory * * Different systems have different cache line sizes * and in some cases i-cache and d-cache line sizes differ from * each other. */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) lhz r7,DCACHEL1LINESIZE(r10) /* Get cache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of cache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r81: dcbst 0,r6 add r6,r6,r7 bdnz 1b sync/* Now invalidate the instruction cache */ lhz r7,ICACHEL1LINESIZE(r10) /* Get Icache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 lhz r9,ICACHEL1LOGLINESIZE(r10) /* Get log-2 of Icache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r82: icbi 0,r6 add r6,r6,r7 bdnz 2b isync blr /* * Like above, but only do the D-cache. * * flush_dcache_range(unsigned long start, unsigned long stop) * * flush all bytes from start to stop-1 inclusive */_GLOBAL(flush_dcache_range)/* * Flush the data cache to memory * * Different systems have different cache line sizes */ LOADADDR(r10,naca) /* Get Naca address */ ld r10,0(r10) lhz r7,DCACHEL1LINESIZE(r10) /* Get dcache line size */ addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 /* ensure we get enough */ lhz r9,DCACHEL1LOGLINESIZE(r10) /* Get log-2 of dcache line size */ srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r80: dcbst 0,r6 add r6,r6,r7 bdnz 0b sync blr/* * Flush a particular page from the data cache to RAM. * Note: this is necessary because the instruction cache does *not* * snoop from the data cache. * * void __flush_dcache_icache(void *page) */_GLOBAL(__flush_dcache_icache)/* * Flush the data cache to memory * * Different systems have different cache line sizes *//* Flush the dcache */ LOADADDR(r7,naca) ld r7,0(r7) clrrdi r3,r3,12 /* Page align */ lhz r4,DCACHEL1LINESPERPAGE(r7) /* Get # dcache lines per page */ lhz r5,DCACHEL1LINESIZE(r7) /* Get dcache line size */ mr r6,r3 mtctr r40: dcbst 0,r6 add r6,r6,r5 bdnz 0b sync/* Now invalidate the icache */ lhz r4,ICACHEL1LINESPERPAGE(r7) /* Get # icache lines per page */ lhz r5,ICACHEL1LINESIZE(r7) /* Get icache line size */ mtctr r41: icbi 0,r3 add r3,r3,r5 bdnz 1b isync blr /* * Copy a whole page. Assumes a 4096B page size. */_GLOBAL(copy_page) clrrdi r3,r3,12 /* Page align */ clrrdi r4,r4,12 /* Page align */ li r5,256 mtctr r5 addi r3,r3,-8 addi r4,r4,-81: ld r6,8(r4) ldu r7,16(r4) std r6,8(r3) stdu r7,16(r3) bdnz+ 1b blr /* * I/O string operations * * insb(port, buf, len) * outsb(port, buf, len) * insw(port, buf, len) * outsw(port, buf, len) * insl(port, buf, len) * outsl(port, buf, len) * insw_ns(port, buf, len) * outsw_ns(port, buf, len) * insl_ns(port, buf, len) * outsl_ns(port, buf, len) * * The *_ns versions don't do byte-swapping. */_GLOBAL(_insb) cmpwi 0,r5,0 mtctr r5 subi r4,r4,1 blelr-00: lbz r5,0(r3) eieio stbu r5,1(r4) bdnz 00b blr_GLOBAL(_outsb) cmpwi 0,r5,0 mtctr r5 subi r4,r4,1 blelr-00: lbzu r5,1(r4) stb r5,0(r3) eieio bdnz 00b blr _GLOBAL(_insw) cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr-00: lhbrx r5,0,r3 eieio sthu r5,2(r4) bdnz 00b blr_GLOBAL(_outsw) cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr-00: lhzu r5,2(r4) eieio sthbrx r5,0,r3 bdnz 00b blr _GLOBAL(_insl) cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr-00: lwbrx r5,0,r3 eieio stwu r5,4(r4) bdnz 00b blr_GLOBAL(_outsl) cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr-00: lwzu r5,4(r4) stwbrx r5,0,r3 eieio bdnz 00b blr _GLOBAL(ide_insw)_GLOBAL(_insw_ns) cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr-00: lhz r5,0(r3) eieio sthu r5,2(r4) bdnz 00b blr_GLOBAL(ide_outsw)_GLOBAL(_outsw_ns) cmpwi 0,r5,0 mtctr r5 subi r4,r4,2 blelr-00: lhzu r5,2(r4) sth r5,0(r3) eieio bdnz 00b blr _GLOBAL(_insl_ns) cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr-00: lwz r5,0(r3) eieio stwu r5,4(r4) bdnz 00b blr_GLOBAL(_outsl_ns) cmpwi 0,r5,0 mtctr r5 subi r4,r4,4 blelr-00: lwzu r5,4(r4) stw r5,0(r3) eieio bdnz 00b blr /* * Extended precision shifts * * R3/R4 has 64 bit value * R5 has shift count * result in R3/R4 * * ashrdi3: XXXYYY/ZZZAAA -> SSSXXX/YYYZZZ * ashldi3: XXXYYY/ZZZAAA -> YYYZZZ/AAA000 * lshrdi3: XXXYYY/ZZZAAA -> 000XXX/YYYZZZ *//* MIKEC: These may no longer be needed...what does gcc expect ? */ _GLOBAL(__ashrdi3) li r6,32 sub r6,r6,r5 slw r7,r3,r6 /* isolate YYY */ srw r4,r4,r5 /* isolate ZZZ */ or r4,r4,r7 /* YYYZZZ */ sraw r3,r3,r5 /* SSSXXX */ blr_GLOBAL(__ashldi3) li r6,32 sub r6,r6,r5 srw r7,r4,r6 /* isolate ZZZ */ slw r4,r4,r5 /* AAA000 */ slw r3,r3,r5 /* YYY--- */ or r3,r3,r7 /* YYYZZZ */ blr_GLOBAL(__lshrdi3) li r6,32 sub r6,r6,r5 slw r7,r3,r6 /* isolate YYY */ srw r4,r4,r5 /* isolate ZZZ */ or r4,r4,r7 /* YYYZZZ */ srw r3,r3,r5 /* 000XXX */ blr_GLOBAL(abs) cmpi 0,r3,0 bge 10f neg r3,r310: blr_GLOBAL(_get_SP) mr r3,r1 /* Close enough */ blr _GLOBAL(_get_PVR) mfspr r3,PVR blr_GLOBAL(_get_PIR) mfspr r3,PIR blr_GLOBAL(_get_HID0) mfspr r3,HID0 blr_GLOBAL(cvt_fd) lfd 0,-4(r5) /* load up fpscr value */ mtfsf 0xff,0 lfs 0,0(r3) stfd 0,0(r4) mffs 0 /* save new fpscr value */ stfd 0,-4(r5) blr_GLOBAL(cvt_df) lfd 0,-4(r5) /* load up fpscr value */ mtfsf 0xff,0 lfd 0,0(r3) stfs 0,0(r4) mffs 0 /* save new fpscr value */ stfd 0,-4(r5) blr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -