⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 head_32.s

📁 linux-2.6.15.6
💻 S
📖 第 1 页 / 共 3 页
字号:
/* *  PowerPC version *    Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) * *  Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP *    Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> *  Adapted for Power Macintosh by Paul Mackerras. *  Low-level exception handlers and MMU support *  rewritten by Paul Mackerras. *    Copyright (C) 1996 Paul Mackerras. *  MPC8xx modifications Copyright (C) 1997 Dan Malek (dmalek@jlc.net). *  Amiga/APUS changes by Jesper Skov (jskov@cygnus.co.uk). * *  This file contains the low-level support and setup for the *  PowerPC platform, including trap and interrupt dispatch. *  (The PPC 8xx embedded CPUs use head_8xx.S instead.) * *  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 <asm/reg.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/pgtable.h>#include <asm/cputable.h>#include <asm/cache.h>#include <asm/thread_info.h>#include <asm/ppc_asm.h>#include <asm/asm-offsets.h>#ifdef CONFIG_APUS#include <asm/amigappc.h>#endif/* 601 only have IBAT; cr0.eq is set on 601 when using this macro */#define LOAD_BAT(n, reg, RA, RB)	\	/* see the comment for clear_bats() -- Cort */ \	li	RA,0;			\	mtspr	SPRN_IBAT##n##U,RA;	\	mtspr	SPRN_DBAT##n##U,RA;	\	lwz	RA,(n*16)+0(reg);	\	lwz	RB,(n*16)+4(reg);	\	mtspr	SPRN_IBAT##n##U,RA;	\	mtspr	SPRN_IBAT##n##L,RB;	\	beq	1f;			\	lwz	RA,(n*16)+8(reg);	\	lwz	RB,(n*16)+12(reg);	\	mtspr	SPRN_DBAT##n##U,RA;	\	mtspr	SPRN_DBAT##n##L,RB;	\1:	.text	.stabs	"arch/powerpc/kernel/",N_SO,0,0,0f	.stabs	"head_32.S",N_SO,0,0,0f0:	.globl	_stext_stext:/* * _start is defined this way because the XCOFF loader in the OpenFirmware * on the powermac expects the entry point to be a procedure descriptor. */	.text	.globl	_start_start:	/*	 * These are here for legacy reasons, the kernel used to	 * need to look like a coff function entry for the pmac	 * but we're always started by some kind of bootloader now.	 *  -- Cort	 */	nop	/* used by __secondary_hold on prep (mtx) and chrp smp */	nop	/* used by __secondary_hold on prep (mtx) and chrp smp */	nop/* PMAC * Enter here with the kernel text, data and bss loaded starting at * 0, running with virtual == physical mapping. * r5 points to the prom entry point (the client interface handler * address).  Address translation is turned on, with the prom * managing the hash table.  Interrupts are disabled.  The stack * pointer (r1) points to just below the end of the half-meg region * from 0x380000 - 0x400000, which is mapped in already. * * If we are booted from MacOS via BootX, we enter with the kernel * image loaded somewhere, and the following values in registers: *  r3: 'BooX' (0x426f6f58) *  r4: virtual address of boot_infos_t *  r5: 0 * * APUS *   r3: 'APUS' *   r4: physical address of memory base *   Linux/m68k style BootInfo structure at &_end. * * PREP * This is jumped to on prep systems right after the kernel is relocated * to its proper place in memory by the boot loader.  The expected layout * of the regs is: *   r3: ptr to residual data *   r4: initrd_start or if no initrd then 0 *   r5: initrd_end - unused if r4 is 0 *   r6: Start of command line string *   r7: End of command line string * * This just gets a minimal mmu environment setup so we can call * start_here() to do the real work. * -- Cort */	.globl	__start__start:/* * We have to do any OF calls before we map ourselves to KERNELBASE, * because OF may have I/O devices mapped into that area * (particularly on CHRP). */	cmpwi	0,r5,0	beq	1f	bl	prom_init	trap1:	mr	r31,r3			/* save parameters */	mr	r30,r4	li	r24,0			/* cpu # *//* * early_init() does the early machine identification and does * the necessary low-level setup and clears the BSS *  -- Cort <cort@fsmlabs.com> */	bl	early_init#ifdef CONFIG_APUS/* On APUS the __va/__pa constants need to be set to the correct * values before continuing. */	mr	r4,r30	bl	fix_mem_constants#endif /* CONFIG_APUS *//* Switch MMU off, clear BATs and flush TLB. At this point, r3 contains * the physical address we are running at, returned by early_init() */ 	bl	mmu_off__after_mmu_off:	bl	clear_bats	bl	flush_tlbs	bl	initial_bats/* * Call setup_cpu for CPU 0 and initialize 6xx Idle */	bl	reloc_offset	li	r24,0			/* cpu# */	bl	call_setup_cpu		/* Call setup_cpu for this CPU */#ifdef CONFIG_6xx	bl	reloc_offset	bl	init_idle_6xx#endif /* CONFIG_6xx */#ifndef CONFIG_APUS/* * We need to run with _start at physical address 0. * On CHRP, we are loaded at 0x10000 since OF on CHRP uses * the exception vectors at 0 (and therefore this copy * overwrites OF's exception vectors with our own). * The MMU is off at this point. */	bl	reloc_offset	mr	r26,r3	addis	r4,r3,KERNELBASE@h	/* current address of _start */	cmpwi	0,r4,0			/* are we already running at 0? */	bne	relocate_kernel#endif /* CONFIG_APUS *//* * we now have the 1st 16M of ram mapped with the bats. * prep needs the mmu to be turned on here, but pmac already has it on. * this shouldn't bother the pmac since it just gets turned on again * as we jump to our code at KERNELBASE. -- Cort * Actually no, pmac doesn't have it on any more. BootX enters with MMU * off, and in other cases, we now turn it off before changing BATs above. */turn_on_mmu:	mfmsr	r0	ori	r0,r0,MSR_DR|MSR_IR	mtspr	SPRN_SRR1,r0	lis	r0,start_here@h	ori	r0,r0,start_here@l	mtspr	SPRN_SRR0,r0	SYNC	RFI				/* enables MMU *//* * We need __secondary_hold as a place to hold the other cpus on * an SMP machine, even when we are running a UP kernel. */	. = 0xc0			/* for prep bootloader */	li	r3,1			/* MTX only has 1 cpu */	.globl	__secondary_hold__secondary_hold:	/* tell the master we're here */	stw	r3,__secondary_hold_acknowledge@l(0)#ifdef CONFIG_SMP100:	lwz	r4,0(0)	/* wait until we're told to start */	cmpw	0,r4,r3	bne	100b	/* our cpu # was at addr 0 - go */	mr	r24,r3			/* cpu # */	b	__secondary_start#else	b	.#endif /* CONFIG_SMP */	.globl	__secondary_hold_spinloop__secondary_hold_spinloop:	.long	0	.globl	__secondary_hold_acknowledge__secondary_hold_acknowledge:	.long	-1/* * Exception entry code.  This code runs with address translation * turned off, i.e. using physical addresses. * We assume sprg3 has the physical address of the current * task's thread_struct. */#define EXCEPTION_PROLOG	\	mtspr	SPRN_SPRG0,r10;	\	mtspr	SPRN_SPRG1,r11;	\	mfcr	r10;		\	EXCEPTION_PROLOG_1;	\	EXCEPTION_PROLOG_2#define EXCEPTION_PROLOG_1	\	mfspr	r11,SPRN_SRR1;		/* check whether user or kernel */ \	andi.	r11,r11,MSR_PR;	\	tophys(r11,r1);			/* use tophys(r1) if kernel */ \	beq	1f;		\	mfspr	r11,SPRN_SPRG3;	\	lwz	r11,THREAD_INFO-THREAD(r11);	\	addi	r11,r11,THREAD_SIZE;	\	tophys(r11,r11);	\1:	subi	r11,r11,INT_FRAME_SIZE	/* alloc exc. frame */#define EXCEPTION_PROLOG_2	\	CLR_TOP32(r11);		\	stw	r10,_CCR(r11);		/* save registers */ \	stw	r12,GPR12(r11);	\	stw	r9,GPR9(r11);	\	mfspr	r10,SPRN_SPRG0;	\	stw	r10,GPR10(r11);	\	mfspr	r12,SPRN_SPRG1;	\	stw	r12,GPR11(r11);	\	mflr	r10;		\	stw	r10,_LINK(r11);	\	mfspr	r12,SPRN_SRR0;	\	mfspr	r9,SPRN_SRR1;	\	stw	r1,GPR1(r11);	\	stw	r1,0(r11);	\	tovirt(r1,r11);			/* set new kernel sp */	\	li	r10,MSR_KERNEL & ~(MSR_IR|MSR_DR); /* can take exceptions */ \	MTMSRD(r10);			/* (except for mach check in rtas) */ \	stw	r0,GPR0(r11);	\	lis	r10,0x7265;		/* put exception frame marker */ \	addi	r10,r10,0x6773;	\	stw	r10,8(r11);	\	SAVE_4GPRS(3, r11);	\	SAVE_2GPRS(7, r11)/* * Note: code which follows this uses cr0.eq (set if from kernel), * r11, r12 (SRR0), and r9 (SRR1). * * Note2: once we have set r1 we are in a position to take exceptions * again, and we could thus set MSR:RI at that point. *//* * Exception vectors. */#define EXCEPTION(n, label, hdlr, xfer)		\	. = n;					\label:						\	EXCEPTION_PROLOG;			\	addi	r3,r1,STACK_FRAME_OVERHEAD;	\	xfer(n, hdlr)#define EXC_XFER_TEMPLATE(n, hdlr, trap, copyee, tfer, ret)	\	li	r10,trap;					\	stw	r10,_TRAP(r11);					\	li	r10,MSR_KERNEL;					\	copyee(r10, r9);					\	bl	tfer;						\i##n:								\	.long	hdlr;						\	.long	ret#define COPY_EE(d, s)		rlwimi d,s,0,16,16#define NOCOPY(d, s)#define EXC_XFER_STD(n, hdlr)		\	EXC_XFER_TEMPLATE(n, hdlr, n, NOCOPY, transfer_to_handler_full,	\			  ret_from_except_full)#define EXC_XFER_LITE(n, hdlr)		\	EXC_XFER_TEMPLATE(n, hdlr, n+1, NOCOPY, transfer_to_handler, \			  ret_from_except)#define EXC_XFER_EE(n, hdlr)		\	EXC_XFER_TEMPLATE(n, hdlr, n, COPY_EE, transfer_to_handler_full, \			  ret_from_except_full)#define EXC_XFER_EE_LITE(n, hdlr)	\	EXC_XFER_TEMPLATE(n, hdlr, n+1, COPY_EE, transfer_to_handler, \			  ret_from_except)/* System reset *//* core99 pmac starts the seconary here by changing the vector, and   putting it back to what it was (unknown_exception) when done.  */#if defined(CONFIG_GEMINI) && defined(CONFIG_SMP)	. = 0x100	b	__secondary_start_gemini#else	EXCEPTION(0x100, Reset, unknown_exception, EXC_XFER_STD)#endif/* Machine check *//* * On CHRP, this is complicated by the fact that we could get a * machine check inside RTAS, and we have no guarantee that certain * critical registers will have the values we expect.  The set of * registers that might have bad values includes all the GPRs * and all the BATs.  We indicate that we are in RTAS by putting * a non-zero value, the address of the exception frame to use, * in SPRG2.  The machine check handler checks SPRG2 and uses its * value if it is non-zero.  If we ever needed to free up SPRG2, * we could use a field in the thread_info or thread_struct instead. * (Other exception handlers assume that r1 is a valid kernel stack * pointer when we take an exception from supervisor mode.) *	-- paulus. */	. = 0x200	mtspr	SPRN_SPRG0,r10	mtspr	SPRN_SPRG1,r11	mfcr	r10#ifdef CONFIG_PPC_CHRP	mfspr	r11,SPRN_SPRG2	cmpwi	0,r11,0	bne	7f#endif /* CONFIG_PPC_CHRP */	EXCEPTION_PROLOG_17:	EXCEPTION_PROLOG_2	addi	r3,r1,STACK_FRAME_OVERHEAD#ifdef CONFIG_PPC_CHRP	mfspr	r4,SPRN_SPRG2	cmpwi	cr1,r4,0	bne	cr1,1f#endif	EXC_XFER_STD(0x200, machine_check_exception)#ifdef CONFIG_PPC_CHRP1:	b	machine_check_in_rtas#endif/* Data access exception. */	. = 0x300DataAccess:	EXCEPTION_PROLOG	mfspr	r10,SPRN_DSISR	andis.	r0,r10,0xa470		/* weird error? */	bne	1f			/* if not, try to put a PTE */	mfspr	r4,SPRN_DAR		/* into the hash table */	rlwinm	r3,r10,32-15,21,21	/* DSISR_STORE -> _PAGE_RW */	bl	hash_page1:	stw	r10,_DSISR(r11)	mr	r5,r10	mfspr	r4,SPRN_DAR	EXC_XFER_EE_LITE(0x300, handle_page_fault)/* Instruction access exception. */	. = 0x400InstructionAccess:	EXCEPTION_PROLOG	andis.	r0,r9,0x4000		/* no pte found? */	beq	1f			/* if so, try to put a PTE */	li	r3,0			/* into the hash table */	mr	r4,r12			/* SRR0 is fault address */	bl	hash_page1:	mr	r4,r12	mr	r5,r9	EXC_XFER_EE_LITE(0x400, handle_page_fault)/* External interrupt */	EXCEPTION(0x500, HardwareInterrupt, do_IRQ, EXC_XFER_LITE)/* Alignment exception */	. = 0x600Alignment:	EXCEPTION_PROLOG	mfspr	r4,SPRN_DAR	stw	r4,_DAR(r11)	mfspr	r5,SPRN_DSISR	stw	r5,_DSISR(r11)	addi	r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_EE(0x600, alignment_exception)/* Program check exception */	EXCEPTION(0x700, ProgramCheck, program_check_exception, EXC_XFER_STD)/* Floating-point unavailable */	. = 0x800FPUnavailable:	EXCEPTION_PROLOG	bne	load_up_fpu		/* if from user, just load it up */	addi	r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception)/* Decrementer */	EXCEPTION(0x900, Decrementer, timer_interrupt, EXC_XFER_LITE)	EXCEPTION(0xa00, Trap_0a, unknown_exception, EXC_XFER_EE)	EXCEPTION(0xb00, Trap_0b, unknown_exception, EXC_XFER_EE)/* System call */	. = 0xc00SystemCall:	EXCEPTION_PROLOG	EXC_XFER_EE_LITE(0xc00, DoSyscall)/* Single step - not used on 601 */	EXCEPTION(0xd00, SingleStep, single_step_exception, EXC_XFER_STD)	EXCEPTION(0xe00, Trap_0e, unknown_exception, EXC_XFER_EE)/* * The Altivec unavailable trap is at 0x0f20.  Foo. * We effectively remap it to 0x3000. * We include an altivec unavailable exception vector even if * not configured for Altivec, so that you can't panic a * non-altivec kernel running on a machine with altivec just * by executing an altivec instruction. */	. = 0xf00	b	Trap_0f	. = 0xf20	b	AltiVecUnavailableTrap_0f:	EXCEPTION_PROLOG	addi	r3,r1,STACK_FRAME_OVERHEAD	EXC_XFER_EE(0xf00, unknown_exception)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -