iseries_misc.s
来自「是关于linux2.5.1的完全源码」· S 代码 · 共 470 行
S
470 行
/* * 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) * updated by Dave Boutcher (boutcher@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 <asm/ppc_asm.h>#include "ppc_defs.h"#include "iSeries_asm.h" .text .align 5#ifdef CONFIG_SMP .comm mmu_hash_lock,4#endif /* CONFIG_SMP */_GLOBAL(is_msr_enabled) mfmsr r3 andi. r3,r3,MSR_EE beqlr /* Return r3=0 indicating disabled */ li r3,1 blr /* Return r3=1 indicating enabled */_GLOBAL(is_soft_enabled) mfspr r3,SPRG1 lbz r3,PACAPROCENABLED(r3) blr_GLOBAL(get_tb64) /* hard disable because we are using a 64-bit register * and we don't want it to get trashed in an interrupt * handler */ mfmsr r5 rlwinm r0,r5,0,17,15 /* clear MSR_EE in r0 */ mtmsr r0 /* hard disable */ mftb r3 rldicl r4,r3,0,32 rldicl r3,r3,32,32 mtmsr r5 /* restore MSR_EE */ blr/* void __save_flags(unsigned long *flags) */_GLOBAL(__save_flags_ptr) mfspr r4,SPRG1 /* Get Paca pointer */ lbz r4,PACAPROCENABLED(r4) stw r4,0(r3) blr_GLOBAL(__save_flags_ptr_end)/* void __restore_flags(unsigned long flags) */ _GLOBAL(__restore_flags) cmpi 0,r3,0 /* Are we enabling? */ beq 0f /* No - then skip interrupt checks */3: mfspr r4,SPRG1 lbz r4,PACAPROCENABLED(r4) cmpi 0,r4,0 /* Are we already enabled? */ bne 0f /* Yes - then skip interrupt checks */ CHECKDECR(r4,r5) bne- do_fake_decrementer CHECKLPQUEUE(r4,r5,r6) bne- do_lost_interrupts2: mfmsr r0 rlwinm r0,r0,0,17,15 /* hard disable */ mtmsr r0 CHECKANYINT(r4,r5,r6) ori r0,r0,MSR_EE beq 1f mtmsr r0 /* hard enable */ b 3b /* process more interrupts */1: mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) mtmsr r0 /* hard enable */ blr0: mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) blr_GLOBAL(__restore_flags_end) _GLOBAL(__cli) mfspr r4,SPRG1 li r3,0 stb r3,PACAPROCENABLED(r4) blr /* Done */_GLOBAL(__cli_end)_GLOBAL(__sti) li r3,1 b __restore_flags_GLOBAL(__sti_end)/* * We were about to enable interrupts but we have to simulate * some interrupts that were lost by enable_irq first. */_GLOBAL(do_lost_interrupts) stwu r1,-32(r1) mflr r0 stw r0,36(r1) stw r3,28(r1)1: bl fake_interrupt bl check_softirqs mfmsr r0 rlwinm r0,r0,0,17,15 /* hard disable */ mtmsr r0 CHECKANYINT(r4,r5,r6) ori r0,r0,MSR_EE beq 2f mtmsr r0 /* hard enable */ b 1b /* process more interrupts */2: lwz r3,28(r1) mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) /* restore soft interrupt state */ mtmsr r0 /* hard enable */ lwz r0,36(r1) mtlr r0 addi r1,r1,32 blr/* * Simulate a decrementer interrupt */do_fake_decrementer: stwu r1,-32(r1) mflr r0 stw r0,36(r1) stw r3,28(r1) bl fake_decrementer bl check_softirqs lwz r0,36(r1) mtlr r0 lwz r3,28(r1) addi r1,r1,32 mfmsr r0 /* hard disable */ rlwinm r0,r0,0,17,15 mtmsr r0 CHECKANYINT(r4,r5,r6) /* Check for any interrupts pending */ ori r0,r0,MSR_EE beq 1f mtmsr r0 /* hard enable */ b do_lost_interrupts /* Handle more interrupts */ 1: mfspr r4,SPRG1 stb r3,PACAPROCENABLED(r4) /* soft enable */ mtmsr r0 /* hard enable */ blr/* * do softirqs if necessary */check_softirqs: stwu r1,-32(r1) mflr r0 stw r0,36(r1) lis r4,irq_stat@ha addi r4,r4,irq_stat@l#ifdef CONFIG_SMP lwz r3,CPU(r2) slwi r3,r3,7 add r4,r4,r3#endif lwz r5,0(r4) lwz r4,4(r4) and. r5,r5,r4 beq+ 2f bl do_softirq2: lwz r0,36(r1) mtlr r0 addi r1,r1,32 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) */_GLOBAL(flush_icache_range)/* * Flush the data cache to memory * * Different models of iSeries's have different cache line sizes * and in some cases i-cache and d-cache line sizes differ from * each other. */ lis r7,iSeries_dcache_line_size@ha lhz r7,iSeries_dcache_line_size@l(r7) 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 */ lis r9,iSeries_log_dcache_line_size@ha lhz r9,iSeries_log_dcache_line_size@l(r9) 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 */ lis r7,iSeries_icache_line_size@ha lhz r7,iSeries_icache_line_size@l(r7) addi r5,r7,-1 andc r6,r3,r5 /* round low to line bdy */ subf r8,r6,r4 /* compute length */ add r8,r8,r5 lis r9,iSeries_log_icache_line_size@ha lhz r9,iSeries_log_icache_line_size@l(r9) srw. r8,r8,r9 /* compute line count */ beqlr /* nothing to do? */ mtctr r82: icbi 0,r6 add r6,r6,r7 bdnz 2b sync isync blr /* * Like above, but only do the D-cache. * * flush_dcache_range(unsigned long start, unsigned long stop) */_GLOBAL(flush_dcache_range)/* * Flush the data cache to memory * * Different models of iSeries's have different cache line sizes */ lis r7,iSeries_dcache_line_size@ha lhz r7,iSeries_dcache_line_size@l(r7) 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 */ lis r9,iSeries_log_dcache_line_size@ha lhz r9,iSeries_log_dcache_line_size@l(r9) 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_page_to_ram(void *page) * void __flush_dcache_icache(void *page) */_GLOBAL(__flush_page_to_ram)_GLOBAL(__flush_dcache_icache)/* * Flush the data cache to memory * * Different models of iSeries's have different cache line sizes *//* Flush the dcache */ rlwinm r3,r3,0,0,19 /* Page align */ lis r4,iSeries_dcache_lines_per_page@ha lhz r4,iSeries_dcache_lines_per_page@l(r4) lis r5,iSeries_dcache_line_size@ha lhz r5,iSeries_dcache_line_size@l(r5) mr r6,r3 mtctr r40: dcbst 0,r6 add r6,r6,r5 bdnz 0b sync/* Now invalidate the icache */ lis r4,iSeries_icache_lines_per_page@ha lhz r4,iSeries_icache_lines_per_page@l(r4) lis r5,iSeries_icache_line_size@ha lhz r5,iSeries_icache_line_size@l(r5) mtctr r41: icbi 0,r3 add r3,r3,r5 bdnz 1b sync isync blr /* * Flush a particular page from the instruction cache. * Note: this is necessary because the instruction cache does *not* * snoop from the data cache. * * void __flush_icache_page(void *page) */_GLOBAL(__flush_icache_page)/* * Different models of iSeries's have different cache line sizes */ /* Invalidate the icache */ rlwinm r3,r3,0,0,19 /* Page align */ lis r4,iSeries_icache_lines_per_page@ha lhz r4,iSeries_icache_lines_per_page@l(r4) lis r5,iSeries_icache_line_size@ha lhz r5,iSeries_icache_line_size@l(r5) mtctr r41: icbi 0,r3 add r3,r3,r5 bdnz 1b sync isync blr /* * Clear a page using the dcbz instruction, which doesn't cause any * memory traffic (except to write out any cache lines which get * displaced). This only works on cacheable memory. */_GLOBAL(clear_page) rlwinm r3,r3,0,0,19 /* Page align */ lis r4,iSeries_dcache_lines_per_page@ha lhz r4,iSeries_dcache_lines_per_page@l(r4) lis r5,iSeries_dcache_line_size@ha lhz r5,iSeries_dcache_line_size@l(r5) mtctr r40: dcbz 0,r3 add r3,r3,r5 bdnz 0b blr/* * Copy a whole page. We use the dcbz instruction on the destination * to reduce memory traffic (it eliminates the unnecessary reads of * the destination into cache). This requires that the destination * is cacheable. */#define COPY_16_BYTES \ lwz r6,4(r4); \ lwz r7,8(r4); \ lwz r8,12(r4); \ lwzu r9,16(r4); \ stw r6,4(r3); \ stw r7,8(r3); \ stw r8,12(r3); \ stwu r9,16(r3)_GLOBAL(copy_page) rlwinm r3,r3,0,0,19 /* Page align */ rlwinm r4,r4,0,0,19 lis r5,iSeries_dcache_lines_per_page@ha lhz r5,iSeries_dcache_lines_per_page@l(r5) lis r6,iSeries_dcache_line_size@ha lhz r0,iSeries_dcache_line_size@l(r6) mtctr r5 addi r3,r3,-4 addi r4,r4,-4 li r10,4 cmpi 0,r0,32 beq do_32_byte_line cmpi 0,r0,64 beq do_64_byte_line cmpi 0,r0,128 beq do_128_byte_line /* We don't have code specifically for this cache line size */ /* Assume that the cache line size is at least 16 (and of */ /* course a multiple of 16) */ /* This code will work for all power-of-2 cache line sizes */ /* from 16 to 4096 */ 1: mr r5,r0 dcbz r10,r30: COPY_16_BYTES addi r5,r5,-16 or. r5,r5,r5 bne 0b bdnz 1b blrdo_32_byte_line: dcbz r10,r3 COPY_16_BYTES COPY_16_BYTES bdnz do_32_byte_line blrdo_64_byte_line: dcbz r10,r3 COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES bdnz do_64_byte_line blrdo_128_byte_line: dcbz r10,r3 COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES COPY_16_BYTES bdnz do_128_byte_line blr
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?