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 + -
显示快捷键?