868 lines · 16.8 KB · Assembly
RawDownload
/* * 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. * * 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/sys.h>#include <asm/unistd.h>#include <asm/errno.h>#include <asm/processor.h>#include <asm/page.h>#include <asm/cache.h>#include <asm/cputable.h>#include <asm/mmu.h>#include <asm/ppc_asm.h>#include <asm/thread_info.h>#include <asm/asm-offsets.h> #ifdef CONFIG_8xx#define ISYNC_8xx isync#else#define ISYNC_8xx#endif	.text 	.align	5_GLOBAL(__delay)	cmpwi	0,r3,0	mtctr	r3	beqlr1:	bdnz	1b	blr /* * 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	lis	r4,1b@ha	addi	r4,r4,1b@l	subf	r3,r4,r3	mtlr	r0	blr /* * add_reloc_offset(x) returns x + reloc_offset(). */_GLOBAL(add_reloc_offset)	mflr	r0	bl	1f1:	mflr	r5	lis	r4,1b@ha	addi	r4,r4,1b@l	subf	r5,r4,r5	add	r3,r3,r5	mtlr	r0	blr /* * sub_reloc_offset(x) returns x - reloc_offset(). */_GLOBAL(sub_reloc_offset)	mflr	r0	bl	1f1:	mflr	r5	lis	r4,1b@ha	addi	r4,r4,1b@l	subf	r5,r4,r5	subf	r3,r5,r3	mtlr	r0	blr /* * reloc_got2 runs through the .got2 section adding an offset * to each entry. */_GLOBAL(reloc_got2)	mflr	r11	lis	r7,__got2_start@ha	addi	r7,r7,__got2_start@l	lis	r8,__got2_end@ha	addi	r8,r8,__got2_end@l	subf	r8,r7,r8	srwi.	r8,r8,2	beqlr	mtctr	r8	bl	1f1:	mflr	r0	lis	r4,1b@ha	addi	r4,r4,1b@l	subf	r0,r4,r0	add	r7,r0,r72:	lwz	r0,0(r7)	add	r0,r0,r3	stw	r0,0(r7)	addi	r7,r7,4	bdnz	2b	mtlr	r11	blr /* * call_setup_cpu - call the setup_cpu function for this cpu * r3 = data offset, r24 = cpu number * * Setup function is called with: *   r3 = data offset *   r4 = ptr to CPU spec (relocated) */_GLOBAL(call_setup_cpu)	addis	r4,r3,cur_cpu_spec@ha	addi	r4,r4,cur_cpu_spec@l	lwz	r4,0(r4)	add	r4,r4,r3	lwz	r5,CPU_SPEC_SETUP(r4)	cmpi	0,r5,0	add	r5,r5,r3	beqlr	mtctr	r5	bctr /* * complement mask on the msr then "or" some values on. *     _nmask_and_or_msr(nmask, value_to_or) */_GLOBAL(_nmask_and_or_msr)	mfmsr	r0		/* Get current msr */	andc	r0,r0,r3	/* And off the bits set in r3 (first parm) */	or	r0,r0,r4	/* Or on the bits in r4 (second parm) */	SYNC			/* Some chip revs have problems here... */	mtmsr	r0		/* Update machine state */	isync	blr			/* Done */  /* * Flush MMU TLB */_GLOBAL(_tlbia)#if defined(CONFIG_40x)	sync			/* Flush to memory before changing mapping */	tlbia	isync			/* Flush shadow TLB */#elif defined(CONFIG_44x)	li	r3,0	sync 	/* Load high watermark */	lis	r4,tlb_44x_hwater@ha	lwz	r5,tlb_44x_hwater@l(r4) 1:	tlbwe	r3,r3,PPC44x_TLB_PAGEID	addi	r3,r3,1	cmpw	0,r3,r5	ble	1b 	isync#else /* !(CONFIG_40x || CONFIG_44x) */#if defined(CONFIG_SMP)	rlwinm	r8,r1,0,0,18	lwz	r8,TI_CPU(r8)	oris	r8,r8,10	mfmsr	r10	SYNC	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */	rlwinm	r0,r0,0,28,26		/* clear DR */	mtmsr	r0	SYNC_601	isync	lis	r9,mmu_hash_lock@h	ori	r9,r9,mmu_hash_lock@l	tophys(r9,r9)10:	lwarx	r7,0,r9	cmpwi	0,r7,0	bne-	10b	stwcx.	r8,0,r9	bne-	10b	sync	tlbia	sync	TLBSYNC	li	r0,0	stw	r0,0(r9)		/* clear mmu_hash_lock */	mtmsr	r10	SYNC_601	isync#else /* CONFIG_SMP */	sync	tlbia	sync#endif /* CONFIG_SMP */#endif /* ! defined(CONFIG_40x) */	blr /* * Flush MMU TLB for a particular address */_GLOBAL(_tlbie)#if defined(CONFIG_40x)	/* We run the search with interrupts disabled because we have to change	 * the PID and I don't want to preempt when that happens.	 */	mfmsr	r5	mfspr	r6,SPRN_PID	wrteei	0	mtspr	SPRN_PID,r4	tlbsx.	r3, 0, r3	mtspr	SPRN_PID,r6	wrtee	r5	bne	10f	sync	/* There are only 64 TLB entries, so r3 < 64, which means bit 25 is clear.	 * Since 25 is the V bit in the TLB_TAG, loading this value will invalidate	 * the TLB entry. */	tlbwe	r3, r3, TLB_TAG	isync10:#elif defined(CONFIG_44x)	mfspr	r5,SPRN_MMUCR	rlwimi	r5,r4,0,24,31			/* Set TID */ 	/* We have to run the search with interrupts disabled, even critical	 * and debug interrupts (in fact the only critical exceptions we have	 * are debug and machine check).  Otherwise  an interrupt which causes	 * a TLB miss can clobber the MMUCR between the mtspr and the tlbsx. */	mfmsr	r4	lis	r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@ha	addi	r6,r6,(MSR_EE|MSR_CE|MSR_ME|MSR_DE)@l	andc	r6,r4,r6	mtmsr	r6	mtspr	SPRN_MMUCR,r5	tlbsx.	r3, 0, r3	mtmsr	r4	bne	10f	sync	/* There are only 64 TLB entries, so r3 < 64,	 * which means bit 22, is clear.  Since 22 is	 * the V bit in the TLB_PAGEID, loading this	 * value will invalidate the TLB entry.	 */	tlbwe	r3, r3, PPC44x_TLB_PAGEID	isync10:#else /* !(CONFIG_40x || CONFIG_44x) */#if defined(CONFIG_SMP)	rlwinm	r8,r1,0,0,18	lwz	r8,TI_CPU(r8)	oris	r8,r8,11	mfmsr	r10	SYNC	rlwinm	r0,r10,0,17,15		/* clear bit 16 (MSR_EE) */	rlwinm	r0,r0,0,28,26		/* clear DR */	mtmsr	r0	SYNC_601	isync	lis	r9,mmu_hash_lock@h	ori	r9,r9,mmu_hash_lock@l	tophys(r9,r9)10:	lwarx	r7,0,r9	cmpwi	0,r7,0	bne-	10b	stwcx.	r8,0,r9	bne-	10b	eieio	tlbie	r3	sync	TLBSYNC	li	r0,0	stw	r0,0(r9)		/* clear mmu_hash_lock */	mtmsr	r10	SYNC_601	isync#else /* CONFIG_SMP */	tlbie	r3	sync#endif /* CONFIG_SMP */#endif /* ! CONFIG_40x */	blr /* * Flush instruction cache. * This is a no-op on the 601. */_GLOBAL(flush_instruction_cache)#if defined(CONFIG_8xx)	isync	lis	r5, IDC_INVALL@h	mtspr	SPRN_IC_CST, r5#elif defined(CONFIG_4xx)#ifdef CONFIG_403GCX	li      r3, 512	mtctr   r3	lis     r4, KERNELBASE@h1:	iccci   0, r4	addi    r4, r4, 16	bdnz    1b#else	lis	r3, KERNELBASE@h	iccci	0,r3#endif#else	mfspr	r3,SPRN_PVR	rlwinm	r3,r3,16,16,31	cmpwi	0,r3,1	beqlr			/* for 601, do nothing */	/* 603/604 processor - use invalidate-all bit in HID0 */	mfspr	r3,SPRN_HID0	ori	r3,r3,HID0_ICFI	mtspr	SPRN_HID0,r3#endif /* CONFIG_8xx/4xx */	isync	blr /* * Write any modified data cache blocks out to memory * and invalidate the corresponding instruction cache blocks. * This is a no-op on the 601. * * __flush_icache_range(unsigned long start, unsigned long stop) */_GLOBAL(__flush_icache_range)BEGIN_FTR_SECTION	blr				/* for 601, do nothing */END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)	li	r5,L1_CACHE_BYTES-1	andc	r3,r3,r5	subf	r4,r3,r4	add	r4,r4,r5	srwi.	r4,r4,L1_CACHE_SHIFT	beqlr	mtctr	r4	mr	r6,r31:	dcbst	0,r3	addi	r3,r3,L1_CACHE_BYTES	bdnz	1b	sync				/* wait for dcbst's to get to ram */	mtctr	r42:	icbi	0,r6	addi	r6,r6,L1_CACHE_BYTES	bdnz	2b	sync				/* additional sync needed on g4 */	isync	blr/* * Write any modified data cache blocks out to memory. * Does not invalidate the corresponding cache lines (especially for * any corresponding instruction cache). * * clean_dcache_range(unsigned long start, unsigned long stop) */_GLOBAL(clean_dcache_range)	li	r5,L1_CACHE_BYTES-1	andc	r3,r3,r5	subf	r4,r3,r4	add	r4,r4,r5	srwi.	r4,r4,L1_CACHE_SHIFT	beqlr	mtctr	r4 1:	dcbst	0,r3	addi	r3,r3,L1_CACHE_BYTES	bdnz	1b	sync				/* wait for dcbst's to get to ram */	blr /* * Write any modified data cache blocks out to memory and invalidate them. * Does not invalidate the corresponding instruction cache blocks. * * flush_dcache_range(unsigned long start, unsigned long stop) */_GLOBAL(flush_dcache_range)	li	r5,L1_CACHE_BYTES-1	andc	r3,r3,r5	subf	r4,r3,r4	add	r4,r4,r5	srwi.	r4,r4,L1_CACHE_SHIFT	beqlr	mtctr	r4 1:	dcbf	0,r3	addi	r3,r3,L1_CACHE_BYTES	bdnz	1b	sync				/* wait for dcbst's to get to ram */	blr /* * Like above, but invalidate the D-cache.  This is used by the 8xx * to invalidate the cache so the PPC core doesn't get stale data * from the CPM (no cache snooping here :-). * * invalidate_dcache_range(unsigned long start, unsigned long stop) */_GLOBAL(invalidate_dcache_range)	li	r5,L1_CACHE_BYTES-1	andc	r3,r3,r5	subf	r4,r3,r4	add	r4,r4,r5	srwi.	r4,r4,L1_CACHE_SHIFT	beqlr	mtctr	r4 1:	dcbi	0,r3	addi	r3,r3,L1_CACHE_BYTES	bdnz	1b	sync				/* wait for dcbi's to get to ram */	blr #ifdef CONFIG_NOT_COHERENT_CACHE/* * 40x cores have 8K or 16K dcache and 32 byte line size. * 44x has a 32K dcache and 32 byte line size. * 8xx has 1, 2, 4, 8K variants. * For now, cover the worst case of the 44x. * Must be called with external interrupts disabled. */#define CACHE_NWAYS	64#define CACHE_NLINES	16 _GLOBAL(flush_dcache_all)	li	r4, (2 * CACHE_NWAYS * CACHE_NLINES)	mtctr	r4	lis     r5, KERNELBASE@h1:	lwz	r3, 0(r5)		/* Load one word from every line */	addi	r5, r5, L1_CACHE_BYTES	bdnz    1b	blr#endif /* CONFIG_NOT_COHERENT_CACHE */ /* * 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. * This is a no-op on the 601 which has a unified cache. * *	void __flush_dcache_icache(void *page) */_GLOBAL(__flush_dcache_icache)BEGIN_FTR_SECTION	blr					/* for 601, do nothing */END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)	rlwinm	r3,r3,0,0,19			/* Get page base address */	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */	mtctr	r4	mr	r6,r30:	dcbst	0,r3				/* Write line to ram */	addi	r3,r3,L1_CACHE_BYTES	bdnz	0b	sync#ifndef CONFIG_44x	/* We don't flush the icache on 44x. Those have a virtual icache	 * and we don't have access to the virtual address here (it's	 * not the page vaddr but where it's mapped in user space). The	 * flushing of the icache on these is handled elsewhere, when	 * a change in the address space occurs, before returning to	 * user space	 */	mtctr	r41:	icbi	0,r6	addi	r6,r6,L1_CACHE_BYTES	bdnz	1b	sync	isync#endif /* CONFIG_44x */	blr /* * Flush a particular page from the data cache to RAM, identified * by its physical address.  We turn off the MMU so we can just use * the physical address (this may be a highmem page without a kernel * mapping). * *	void __flush_dcache_icache_phys(unsigned long physaddr) */_GLOBAL(__flush_dcache_icache_phys)BEGIN_FTR_SECTION	blr					/* for 601, do nothing */END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE)	mfmsr	r10	rlwinm	r0,r10,0,28,26			/* clear DR */	mtmsr	r0	isync	rlwinm	r3,r3,0,0,19			/* Get page base address */	li	r4,4096/L1_CACHE_BYTES	/* Number of lines in a page */	mtctr	r4	mr	r6,r30:	dcbst	0,r3				/* Write line to ram */	addi	r3,r3,L1_CACHE_BYTES	bdnz	0b	sync

Lines 1–500 of 868.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t