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

📄 head_64.s

📁 linux-2.6.15.6
💻 S
📖 第 1 页 / 共 4 页
字号:
/* *  arch/ppc64/kernel/head.S * *  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. * *  Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and *    Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com * *  This file contains the low-level support and setup for the *  PowerPC-64 platform, including trap and interrupt dispatch. * *  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/threads.h>#include <asm/reg.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/ppc_asm.h>#include <asm/asm-offsets.h>#include <asm/bug.h>#include <asm/cputable.h>#include <asm/setup.h>#include <asm/hvcall.h>#include <asm/iseries/lpar_map.h>#include <asm/thread_info.h>#ifdef CONFIG_PPC_ISERIES#define DO_SOFT_DISABLE#endif/* * We layout physical memory as follows: * 0x0000 - 0x00ff : Secondary processor spin code * 0x0100 - 0x2fff : pSeries Interrupt prologs * 0x3000 - 0x5fff : interrupt support, iSeries and common interrupt prologs * 0x6000 - 0x6fff : Initial (CPU0) segment table * 0x7000 - 0x7fff : FWNMI data area * 0x8000 -        : Early init and support code *//* *   SPRG Usage * *   Register	Definition * *   SPRG0	reserved for hypervisor *   SPRG1	temp - used to save gpr *   SPRG2	temp - used to save gpr *   SPRG3	virt addr of paca *//* * Entering into this code we make the following assumptions: *  For pSeries: *   1. The MMU is off & open firmware is running in real mode. *   2. The kernel is entered at __start * *  For iSeries: *   1. The MMU is on (as it always is for iSeries) *   2. The kernel is entered at system_reset_iSeries */	.text	.globl  _stext_stext:#ifdef CONFIG_PPC_MULTIPLATFORM_GLOBAL(__start)	/* NOP this out unconditionally */BEGIN_FTR_SECTION	b	.__start_initialization_multiplatformEND_FTR_SECTION(0, 1)#endif /* CONFIG_PPC_MULTIPLATFORM */	/* Catch branch to 0 in real mode */	trap#ifdef CONFIG_PPC_ISERIES	/*	 * At offset 0x20, there is a pointer to iSeries LPAR data.	 * This is required by the hypervisor	 */	. = 0x20	.llong hvReleaseData-KERNELBASE	/*	 * At offset 0x28 and 0x30 are offsets to the mschunks_map	 * array (used by the iSeries LPAR debugger to do translation	 * between physical addresses and absolute addresses) and	 * to the pidhash table (also used by the debugger)	 */	.llong mschunks_map-KERNELBASE	.llong 0	/* pidhash-KERNELBASE SFRXXX */	/* Offset 0x38 - Pointer to start of embedded System.map */	.globl	embedded_sysmap_startembedded_sysmap_start:	.llong	0	/* Offset 0x40 - Pointer to end of embedded System.map */	.globl	embedded_sysmap_endembedded_sysmap_end:	.llong	0#endif /* CONFIG_PPC_ISERIES */	/* Secondary processors spin on this value until it goes to 1. */	.globl  __secondary_hold_spinloop__secondary_hold_spinloop:	.llong	0x0	/* Secondary processors write this value with their cpu # */	/* after they enter the spin loop immediately below.	  */	.globl	__secondary_hold_acknowledge__secondary_hold_acknowledge:	.llong	0x0	. = 0x60/* * The following code is used on pSeries to hold secondary processors * in a spin loop after they have been freed from OpenFirmware, but * before the bulk of the kernel has been relocated.  This code * is relocated to physical address 0x60 before prom_init is run. * All of it must fit below the first exception vector at 0x100. */_GLOBAL(__secondary_hold)	mfmsr	r24	ori	r24,r24,MSR_RI	mtmsrd	r24			/* RI on */	/* Grab our linux cpu number */	mr	r24,r3	/* Tell the master cpu we're here */	/* Relocation is off & we are located at an address less */	/* than 0x100, so only need to grab low order offset.    */	std	r24,__secondary_hold_acknowledge@l(0)	sync	/* All secondary cpus wait here until told to start. */100:	ld	r4,__secondary_hold_spinloop@l(0)	cmpdi	0,r4,1	bne	100b#ifdef CONFIG_HMT	b	.hmt_init#else#ifdef CONFIG_SMP	mr	r3,r24	b	.pSeries_secondary_smp_init#else	BUG_OPCODE#endif#endif/* This value is used to mark exception frames on the stack. */	.section ".toc","aw"exception_marker:	.tc	ID_72656773_68657265[TC],0x7265677368657265	.text/* * The following macros define the code that appears as * the prologue to each of the exception handlers.  They * are split into two parts to allow a single kernel binary * to be used for pSeries and iSeries. * LOL.  One day... - paulus *//* * We make as much of the exception code common between native * exception handlers (including pSeries LPAR) and iSeries LPAR * implementations as possible. *//* * This is the start of the interrupt handlers for pSeries * This code runs with relocation off. */#define EX_R9		0#define EX_R10		8#define EX_R11		16#define EX_R12		24#define EX_R13		32#define EX_SRR0		40#define EX_DAR		48#define EX_DSISR	56#define EX_CCR		60#define EX_R3		64#define EX_LR		72#define EXCEPTION_PROLOG_PSERIES(area, label)				\	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\	std	r10,area+EX_R10(r13);					\	std	r11,area+EX_R11(r13);					\	std	r12,area+EX_R12(r13);					\	mfspr	r9,SPRN_SPRG1;						\	std	r9,area+EX_R13(r13);					\	mfcr	r9;							\	clrrdi	r12,r13,32;		/* get high part of &label */	\	mfmsr	r10;							\	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\	ori	r12,r12,(label)@l;	/* virt addr of handler */	\	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\	mtspr	SPRN_SRR0,r12;						\	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\	mtspr	SPRN_SRR1,r10;						\	rfid;								\	b	.	/* prevent speculative execution *//* * This is the start of the interrupt handlers for iSeries * This code runs with relocation on. */#define EXCEPTION_PROLOG_ISERIES_1(area)				\	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\	std	r10,area+EX_R10(r13);					\	std	r11,area+EX_R11(r13);					\	std	r12,area+EX_R12(r13);					\	mfspr	r9,SPRN_SPRG1;						\	std	r9,area+EX_R13(r13);					\	mfcr	r9#define EXCEPTION_PROLOG_ISERIES_2					\	mfmsr	r10;							\	ld	r11,PACALPPACA+LPPACASRR0(r13);				\	ld	r12,PACALPPACA+LPPACASRR1(r13);				\	ori	r10,r10,MSR_RI;						\	mtmsrd	r10,1/* * The common exception prolog is used for all except a few exceptions * such as a segment miss on a kernel address.  We have to be prepared * to take another exception from the point where we first touch the * kernel stack onwards. * * On entry r13 points to the paca, r9-r13 are saved in the paca, * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and * SRR1, and relocation is on. */#define EXCEPTION_PROLOG_COMMON(n, area)				   \	andi.	r10,r12,MSR_PR;		/* See if coming from user	*/ \	mr	r10,r1;			/* Save r1			*/ \	subi	r1,r1,INT_FRAME_SIZE;	/* alloc frame on kernel stack	*/ \	beq-	1f;							   \	ld	r1,PACAKSAVE(r13);	/* kernel stack to use		*/ \1:	cmpdi	cr1,r1,0;		/* check if r1 is in userspace	*/ \	bge-	cr1,bad_stack;		/* abort if it is		*/ \	std	r9,_CCR(r1);		/* save CR in stackframe	*/ \	std	r11,_NIP(r1);		/* save SRR0 in stackframe	*/ \	std	r12,_MSR(r1);		/* save SRR1 in stackframe	*/ \	std	r10,0(r1);		/* make stack chain pointer	*/ \	std	r0,GPR0(r1);		/* save r0 in stackframe	*/ \	std	r10,GPR1(r1);		/* save r1 in stackframe	*/ \	std	r2,GPR2(r1);		/* save r2 in stackframe	*/ \	SAVE_4GPRS(3, r1);		/* save r3 - r6 in stackframe	*/ \	SAVE_2GPRS(7, r1);		/* save r7, r8 in stackframe	*/ \	ld	r9,area+EX_R9(r13);	/* move r9, r10 to stackframe	*/ \	ld	r10,area+EX_R10(r13);					   \	std	r9,GPR9(r1);						   \	std	r10,GPR10(r1);						   \	ld	r9,area+EX_R11(r13);	/* move r11 - r13 to stackframe	*/ \	ld	r10,area+EX_R12(r13);					   \	ld	r11,area+EX_R13(r13);					   \	std	r9,GPR11(r1);						   \	std	r10,GPR12(r1);						   \	std	r11,GPR13(r1);						   \	ld	r2,PACATOC(r13);	/* get kernel TOC into r2	*/ \	mflr	r9;			/* save LR in stackframe	*/ \	std	r9,_LINK(r1);						   \	mfctr	r10;			/* save CTR in stackframe	*/ \	std	r10,_CTR(r1);						   \	mfspr	r11,SPRN_XER;		/* save XER in stackframe	*/ \	std	r11,_XER(r1);						   \	li	r9,(n)+1;						   \	std	r9,_TRAP(r1);		/* set trap number		*/ \	li	r10,0;							   \	ld	r11,exception_marker@toc(r2);				   \	std	r10,RESULT(r1);		/* clear regs->result		*/ \	std	r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame	*//* * Exception vectors. */#define STD_EXCEPTION_PSERIES(n, label)			\	. = n;						\	.globl label##_pSeries;				\label##_pSeries:					\	HMT_MEDIUM;					\	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\	RUNLATCH_ON(r13);				\	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common)#define STD_EXCEPTION_ISERIES(n, label, area)		\	.globl label##_iSeries;				\label##_iSeries:					\	HMT_MEDIUM;					\	mtspr	SPRN_SPRG1,r13;		/* save r13 */	\	RUNLATCH_ON(r13);				\	EXCEPTION_PROLOG_ISERIES_1(area);		\	EXCEPTION_PROLOG_ISERIES_2;			\	b	label##_common#define MASKABLE_EXCEPTION_ISERIES(n, label)				\	.globl label##_iSeries;						\label##_iSeries:							\	HMT_MEDIUM;							\	mtspr	SPRN_SPRG1,r13;		/* save r13 */			\	RUNLATCH_ON(r13);						\	EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN);				\	lbz	r10,PACAPROCENABLED(r13);				\	cmpwi	0,r10,0;						\	beq-	label##_iSeries_masked;					\	EXCEPTION_PROLOG_ISERIES_2;					\	b	label##_common;						\#ifdef DO_SOFT_DISABLE#define DISABLE_INTS				\	lbz	r10,PACAPROCENABLED(r13);	\	li	r11,0;				\	std	r10,SOFTE(r1);			\	mfmsr	r10;				\	stb	r11,PACAPROCENABLED(r13);	\	ori	r10,r10,MSR_EE;			\	mtmsrd	r10,1#define ENABLE_INTS				\	lbz	r10,PACAPROCENABLED(r13);	\	mfmsr	r11;				\	std	r10,SOFTE(r1);			\	ori	r11,r11,MSR_EE;			\	mtmsrd	r11,1#else	/* hard enable/disable interrupts */#define DISABLE_INTS#define ENABLE_INTS				\	ld	r12,_MSR(r1);			\	mfmsr	r11;				\	rlwimi	r11,r12,0,MSR_EE;		\	mtmsrd	r11,1#endif#define STD_EXCEPTION_COMMON(trap, label, hdlr)		\	.align	7;					\	.globl label##_common;				\label##_common:						\	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\	DISABLE_INTS;					\	bl	.save_nvgprs;				\	addi	r3,r1,STACK_FRAME_OVERHEAD;		\	bl	hdlr;					\	b	.ret_from_except#define STD_EXCEPTION_COMMON_LITE(trap, label, hdlr)	\	.align	7;					\	.globl label##_common;				\label##_common:						\	EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN);	\	DISABLE_INTS;					\	addi	r3,r1,STACK_FRAME_OVERHEAD;		\	bl	hdlr;					\	b	.ret_from_except_lite/* * Start of pSeries system interrupt routines */	. = 0x100	.globl __start_interrupts__start_interrupts:	STD_EXCEPTION_PSERIES(0x100, system_reset)	. = 0x200_machine_check_pSeries:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13		/* save r13 */	RUNLATCH_ON(r13)	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)	. = 0x300	.globl data_access_pSeriesdata_access_pSeries:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13BEGIN_FTR_SECTION	mtspr	SPRN_SPRG2,r12	mfspr	r13,SPRN_DAR	mfspr	r12,SPRN_DSISR	srdi	r13,r13,60	rlwimi	r13,r12,16,0x20	mfcr	r12	cmpwi	r13,0x2c	beq	.do_stab_bolted_pSeries	mtcrf	0x80,r12	mfspr	r12,SPRN_SPRG2END_FTR_SECTION_IFCLR(CPU_FTR_SLB)	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common)	. = 0x380	.globl data_access_slb_pSeriesdata_access_slb_pSeries:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13	RUNLATCH_ON(r13)	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */	std	r3,PACA_EXSLB+EX_R3(r13)	mfspr	r3,SPRN_DAR	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */	mfcr	r9#ifdef __DISABLED__	/* Keep that around for when we re-implement dynamic VSIDs */	cmpdi	r3,0	bge	slb_miss_user_pseries#endif /* __DISABLED__ */	std	r10,PACA_EXSLB+EX_R10(r13)	std	r11,PACA_EXSLB+EX_R11(r13)	std	r12,PACA_EXSLB+EX_R12(r13)	mfspr	r10,SPRN_SPRG1	std	r10,PACA_EXSLB+EX_R13(r13)	mfspr	r12,SPRN_SRR1		/* and SRR1 */	b	.slb_miss_realmode	/* Rel. branch works in real mode */	STD_EXCEPTION_PSERIES(0x400, instruction_access)	. = 0x480	.globl instruction_access_slb_pSeriesinstruction_access_slb_pSeries:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13	RUNLATCH_ON(r13)	mfspr	r13,SPRN_SPRG3		/* get paca address into r13 */	std	r3,PACA_EXSLB+EX_R3(r13)	mfspr	r3,SPRN_SRR0		/* SRR0 is faulting address */	std	r9,PACA_EXSLB+EX_R9(r13)	/* save r9 - r12 */	mfcr	r9#ifdef __DISABLED__	/* Keep that around for when we re-implement dynamic VSIDs */	cmpdi	r3,0	bge	slb_miss_user_pseries#endif /* __DISABLED__ */	std	r10,PACA_EXSLB+EX_R10(r13)	std	r11,PACA_EXSLB+EX_R11(r13)	std	r12,PACA_EXSLB+EX_R12(r13)	mfspr	r10,SPRN_SPRG1	std	r10,PACA_EXSLB+EX_R13(r13)	mfspr	r12,SPRN_SRR1		/* and SRR1 */	b	.slb_miss_realmode	/* Rel. branch works in real mode */	STD_EXCEPTION_PSERIES(0x500, hardware_interrupt)	STD_EXCEPTION_PSERIES(0x600, alignment)	STD_EXCEPTION_PSERIES(0x700, program_check)	STD_EXCEPTION_PSERIES(0x800, fp_unavailable)	STD_EXCEPTION_PSERIES(0x900, decrementer)	STD_EXCEPTION_PSERIES(0xa00, trap_0a)	STD_EXCEPTION_PSERIES(0xb00, trap_0b)	. = 0xc00	.globl	system_call_pSeriessystem_call_pSeries:	HMT_MEDIUM	RUNLATCH_ON(r9)	mr	r9,r13	mfmsr	r10	mfspr	r13,SPRN_SPRG3	mfspr	r11,SPRN_SRR0	clrrdi	r12,r13,32	oris	r12,r12,system_call_common@h	ori	r12,r12,system_call_common@l	mtspr	SPRN_SRR0,r12	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI	mfspr	r12,SPRN_SRR1	mtspr	SPRN_SRR1,r10	rfid	b	.	/* prevent speculative execution */	STD_EXCEPTION_PSERIES(0xd00, single_step)	STD_EXCEPTION_PSERIES(0xe00, trap_0e)	/* We need to deal with the Altivec unavailable exception	 * here which is at 0xf20, thus in the middle of the	 * prolog code of the PerformanceMonitor one. A little	 * trickery is thus necessary	 */	. = 0xf00	b	performance_monitor_pSeries	STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable)

⌨️ 快捷键说明

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