1457 lines · 28.9 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/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/cputable.h>#include <asm/mmu.h>#include <asm/ppc_asm.h>#include <asm/thread_info.h>#include <asm/offsets.h> 	.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 /* * identify_cpu, * called with r3 = data offset and r4 = CPU number * doesn't change r3 */_GLOBAL(identify_cpu)	addis	r8,r3,cpu_specs@ha	addi	r8,r8,cpu_specs@l	mfpvr	r71:	lwz	r5,CPU_SPEC_PVR_MASK(r8)	and	r5,r5,r7	lwz	r6,CPU_SPEC_PVR_VALUE(r8)	cmplw	0,r6,r5	beq	1f	addi	r8,r8,CPU_SPEC_ENTRY_SIZE	b	1b1:	addis	r6,r3,cur_cpu_spec@ha	addi	r6,r6,cur_cpu_spec@l	slwi	r4,r4,2	sub	r8,r8,r3	stwx	r8,r4,r6	blr /* * do_cpu_ftr_fixups - goes through the list of CPU feature fixups * and writes nop's over sections of code that don't apply for this cpu. * r3 = data offset (not changed) */_GLOBAL(do_cpu_ftr_fixups)	/* Get CPU 0 features */	addis	r6,r3,cur_cpu_spec@ha	addi	r6,r6,cur_cpu_spec@l	lwz	r4,0(r6)	add	r4,r4,r3	lwz	r4,CPU_SPEC_FEATURES(r4) 	/* Get the fixup table */	addis	r6,r3,__start___ftr_fixup@ha	addi	r6,r6,__start___ftr_fixup@l	addis	r7,r3,__stop___ftr_fixup@ha	addi	r7,r7,__stop___ftr_fixup@l 	/* Do the fixup */1:	cmplw	0,r6,r7	bgelr	addi	r6,r6,16	lwz	r8,-16(r6)	/* mask */	and	r8,r8,r4	lwz	r9,-12(r6)	/* value */	cmplw	0,r8,r9	beq	1b	lwz	r8,-8(r6)	/* section begin */	lwz	r9,-4(r6)	/* section end */	subf.	r9,r8,r9	beq	1b	/* write nops over the section of code */	/* todo: if large section, add a branch at the start of it */	srwi	r9,r9,2	mtctr	r9	add	r8,r8,r3	lis	r0,0x60000000@h	/* nop */3:	stw	r0,0(r8)	andi.	r10,r4,CPU_FTR_SPLIT_ID_CACHE@l	beq	2f	dcbst	0,r8		/* suboptimal, but simpler */	sync	icbi	0,r82:	addi	r8,r8,4	bdnz	3b	sync			/* additional sync needed on g4 */	isync	b	1b /* * 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 = CPU number *   r5 = ptr to CPU spec (relocated) */_GLOBAL(call_setup_cpu)	addis	r5,r3,cur_cpu_spec@ha	addi	r5,r5,cur_cpu_spec@l	slwi	r4,r24,2	lwzx	r5,r4,r5	add	r5,r5,r3	lwz	r6,CPU_SPEC_SETUP(r5)	add	r6,r6,r3	mtctr	r6	mr	r4,r24	bctr #if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) /* This gets called by via-pmu.c to switch the PLL selection * on 750fx CPU. This function should really be moved to some * other place (as most of the cpufreq code in via-pmu */_GLOBAL(low_choose_750fx_pll)	/* Clear MSR:EE */	mfmsr	r7	rlwinm	r0,r7,0,17,15	mtmsr	r0 	/* If switching to PLL1, disable HID0:BTIC */	cmplwi	cr0,r3,0	beq	1f	mfspr	r5,SPRN_HID0	rlwinm	r5,r5,0,27,25	sync	mtspr	SPRN_HID0,r5	isync	sync 1:	/* Calc new HID1 value */	mfspr	r4,SPRN_HID1	/* Build a HID1:PS bit from parameter */	rlwinm	r5,r3,16,15,15	/* Clear out HID1:PS from value read */	rlwinm	r4,r4,0,16,14	/* Could have I used rlwimi here ? */	or	r4,r4,r5	mtspr	SPRN_HID1,r4 	/* Store new HID1 image */	rlwinm	r6,r1,0,0,18	lwz	r6,TI_CPU(r6)	slwi	r6,r6,2	addis	r6,r6,nap_save_hid1@ha	stw	r4,nap_save_hid1@l(r6) 	/* If switching to PLL0, enable HID0:BTIC */	cmplwi	cr0,r3,0	bne	1f	mfspr	r5,SPRN_HID0	ori	r5,r5,HID0_BTIC	sync	mtspr	SPRN_HID0,r5	isync	sync 1:	/* Return */	mtmsr	r7	blr _GLOBAL(low_choose_7447a_dfs)	/* Clear MSR:EE */	mfmsr	r7	rlwinm	r0,r7,0,17,15	mtmsr	r0		/* Calc new HID1 value */	mfspr	r4,SPRN_HID1	insrwi	r4,r3,1,9	/* insert parameter into bit 9 */	sync	mtspr	SPRN_HID1,r4	sync	isync 	/* Return */	mtmsr	r7	blr #endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ /* void local_save_flags_ptr(unsigned long *flags) */_GLOBAL(local_save_flags_ptr)	mfmsr	r4	stw	r4,0(r3)	blr	/*	 * Need these nops here for taking over save/restore to	 * handle lost intrs	 * -- Cort	 */	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop_GLOBAL(local_save_flags_ptr_end) /* void local_irq_restore(unsigned long flags) */_GLOBAL(local_irq_restore)/* * 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 */	mfmsr 	r4	/* Copy all except the MSR_EE bit from r4 (current MSR value)	   to r3.  This is the sort of thing the rlwimi instruction is	   designed for.  -- paulus. */	rlwimi	r3,r4,0,17,15	 /* Check if things are setup the way we want _already_. */	cmpw	0,r3,r4	beqlr1:	SYNC	mtmsr	r3	SYNC	blr	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop_GLOBAL(local_irq_restore_end) _GLOBAL(local_irq_disable)	mfmsr	r0		/* Get current interrupt state */	rlwinm	r3,r0,16+1,32-1,31	/* Extract old value of 'EE' */	rlwinm	r0,r0,0,17,15	/* clear MSR_EE in r0 */	SYNC			/* Some chip revs have problems here... */	mtmsr	r0		/* Update machine state */	blr			/* Done */	/*	 * Need these nops here for taking over save/restore to	 * handle lost intrs	 * -- Cort	 */	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop_GLOBAL(local_irq_disable_end) _GLOBAL(local_irq_enable)	mfmsr	r3		/* Get current state */	ori	r3,r3,MSR_EE	/* Turn on 'EE' bit */	SYNC			/* Some chip revs have problems here... */	mtmsr	r3		/* Update machine state */	blr	/*	 * Need these nops here for taking over save/restore to	 * handle lost intrs	 * -- Cort	 */	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop	nop_GLOBAL(local_irq_enable_end) /* * 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#elif defined(CONFIG_FSL_BOOKE)	/* Invalidate all entries in TLB0 */	li	r3, 0x04	tlbivax	0,3	/* Invalidate all entries in TLB1 */	li	r3, 0x0c	tlbivax	0,3	/* Invalidate all entries in TLB2 */	li	r3, 0x14	tlbivax	0,3	/* Invalidate all entries in TLB3 */	li	r3, 0x1c	tlbivax	0,3	msync#ifdef CONFIG_SMP	tlbsync#endif /* CONFIG_SMP */#else /* !(CONFIG_40x || CONFIG_44x || CONFIG_FSL_BOOKE) */#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)	tlbsx.	r3, 0, r3	bne	10f

Lines 1–500 of 1457.