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

📄 head_64.s

📁 linux 内核源代码
💻 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. * *  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/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>#include <asm/firmware.h>#include <asm/page_64.h>#include <asm/exception.h>#define DO_SOFT_DISABLE/* * 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:_GLOBAL(__start)	/* NOP this out unconditionally */BEGIN_FTR_SECTION	b	.__start_initialization_multiplatformEND_FTR_SECTION(0, 1)	/* Catch branch to 0 in real mode */	trap	/* 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#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#endif /* CONFIG_PPC_ISERIES */	. = 0x60/* * The following code is used to hold secondary processors * in a spin loop after they have entered the kernel, 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 physical 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#if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)	LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)	mtctr	r4	mr	r3,r24	bctr#else	BUG_OPCODE#endif/* This value is used to mark exception frames on the stack. */	.section ".toc","aw"exception_marker:	.tc	ID_72656773_68657265[TC],0x7265677368657265	.text/* * This is the start of the interrupt handlers for pSeries * This code runs with relocation off. */	. = 0x100	.globl __start_interrupts__start_interrupts:	STD_EXCEPTION_PSERIES(0x100, system_reset)	. = 0x200_machine_check_pSeries:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13		/* save 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	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	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 */	MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)	STD_EXCEPTION_PSERIES(0x600, alignment)	STD_EXCEPTION_PSERIES(0x700, program_check)	STD_EXCEPTION_PSERIES(0x800, fp_unavailable)	MASKABLE_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	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)#ifdef CONFIG_CBE_RAS	HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error)#endif /* CONFIG_CBE_RAS */	STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint)#ifdef CONFIG_CBE_RAS	HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance)#endif /* CONFIG_CBE_RAS */	STD_EXCEPTION_PSERIES(0x1700, altivec_assist)#ifdef CONFIG_CBE_RAS	HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal)#endif /* CONFIG_CBE_RAS */	. = 0x3000/*** pSeries interrupt support ***/	/* moved from 0xf00 */	STD_EXCEPTION_PSERIES(., performance_monitor)/* * An interrupt came in while soft-disabled; clear EE in SRR1, * clear paca->hard_enabled and return. */masked_interrupt:	stb	r10,PACAHARDIRQEN(r13)	mtcrf	0x80,r9	ld	r9,PACA_EXGEN+EX_R9(r13)	mfspr	r10,SPRN_SRR1	rldicl	r10,r10,48,1		/* clear MSR_EE */	rotldi	r10,r10,16	mtspr	SPRN_SRR1,r10	ld	r10,PACA_EXGEN+EX_R10(r13)	mfspr	r13,SPRN_SPRG1	rfid	b	.	.align	7do_stab_bolted_pSeries:	mtcrf	0x80,r12	mfspr	r12,SPRN_SPRG2	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)/* * We have some room here  we use that to put * the peries slb miss user trampoline code so it's reasonably * away from slb_miss_user_common to avoid problems with rfid * * This is used for when the SLB miss handler has to go virtual, * which doesn't happen for now anymore but will once we re-implement * dynamic VSIDs for shared page tables */#ifdef __DISABLED__slb_miss_user_pseries:	std	r10,PACA_EXGEN+EX_R10(r13)	std	r11,PACA_EXGEN+EX_R11(r13)	std	r12,PACA_EXGEN+EX_R12(r13)	mfspr	r10,SPRG1	ld	r11,PACA_EXSLB+EX_R9(r13)	ld	r12,PACA_EXSLB+EX_R3(r13)	std	r10,PACA_EXGEN+EX_R13(r13)	std	r11,PACA_EXGEN+EX_R9(r13)	std	r12,PACA_EXGEN+EX_R3(r13)	clrrdi	r12,r13,32	mfmsr	r10	mfspr	r11,SRR0			/* save SRR0 */	ori	r12,r12,slb_miss_user_common@l	/* virt addr of handler */	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI	mtspr	SRR0,r12	mfspr	r12,SRR1			/* and SRR1 */	mtspr	SRR1,r10	rfid	b	.				/* prevent spec. execution */#endif /* __DISABLED__ */#ifdef CONFIG_PPC_PSERIES/* * Vectors for the FWNMI option.  Share common code. */	.globl system_reset_fwnmi      .align 7system_reset_fwnmi:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13		/* save r13 */	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)	.globl machine_check_fwnmi      .align 7machine_check_fwnmi:	HMT_MEDIUM	mtspr	SPRN_SPRG1,r13		/* save r13 */	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)#endif /* CONFIG_PPC_PSERIES *//*** Common interrupt handlers ***/	STD_EXCEPTION_COMMON(0x100, system_reset, .system_reset_exception)	/*	 * Machine check is different because we use a different	 * save area: PACA_EXMC instead of PACA_EXGEN.	 */	.align	7	.globl machine_check_commonmachine_check_common:	EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC)	FINISH_NAP	DISABLE_INTS	bl	.save_nvgprs	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.machine_check_exception	b	.ret_from_except	STD_EXCEPTION_COMMON_LITE(0x900, decrementer, .timer_interrupt)	STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)	STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)	STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)	STD_EXCEPTION_COMMON(0xe00, trap_0e, .unknown_exception)	STD_EXCEPTION_COMMON_IDLE(0xf00, performance_monitor, .performance_monitor_exception)	STD_EXCEPTION_COMMON(0x1300, instruction_breakpoint, .instruction_breakpoint_exception)#ifdef CONFIG_ALTIVEC	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .altivec_assist_exception)#else	STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception)#endif#ifdef CONFIG_CBE_RAS	STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception)	STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception)	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)#endif /* CONFIG_CBE_RAS *//* * Here we have detected that the kernel stack pointer is bad. * R9 contains the saved CR, r13 points to the paca, * r10 contains the (bad) kernel stack pointer, * r11 and r12 contain the saved SRR0 and SRR1. * We switch to using an emergency stack, save the registers there, * and call kernel_bad_stack(), which panics. */bad_stack:	ld	r1,PACAEMERGSP(r13)	subi	r1,r1,64+INT_FRAME_SIZE	std	r9,_CCR(r1)	std	r10,GPR1(r1)	std	r11,_NIP(r1)	std	r12,_MSR(r1)	mfspr	r11,SPRN_DAR	mfspr	r12,SPRN_DSISR	std	r11,_DAR(r1)	std	r12,_DSISR(r1)	mflr	r10	mfctr	r11	mfxer	r12	std	r10,_LINK(r1)	std	r11,_CTR(r1)	std	r12,_XER(r1)	SAVE_GPR(0,r1)	SAVE_GPR(2,r1)	SAVE_4GPRS(3,r1)	SAVE_2GPRS(7,r1)	SAVE_10GPRS(12,r1)	SAVE_10GPRS(22,r1)	lhz	r12,PACA_TRAP_SAVE(r13)	std	r12,_TRAP(r1)	addi	r11,r1,INT_FRAME_SIZE	std	r11,0(r1)	li	r12,0	std	r12,0(r11)	ld	r2,PACATOC(r13)1:	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.kernel_bad_stack	b	1b/* * Return from an exception with minimal checks. * The caller is assumed to have done EXCEPTION_PROLOG_COMMON. * If interrupts have been enabled, or anything has been * done that might have changed the scheduling status of * any task or sent any task a signal, you should use * ret_from_except or ret_from_except_lite instead of this. */fast_exc_return_irq:			/* restores irq state too */	ld	r3,SOFTE(r1)	ld	r12,_MSR(r1)	stb	r3,PACASOFTIRQEN(r13)	/* restore paca->soft_enabled */	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */	b	1f	.globl	fast_exception_returnfast_exception_return:	ld	r12,_MSR(r1)1:	ld	r11,_NIP(r1)	andi.	r3,r12,MSR_RI		/* check if RI is set */	beq-	unrecov_fer#ifdef CONFIG_VIRT_CPU_ACCOUNTING	andi.	r3,r12,MSR_PR	beq	2f	ACCOUNT_CPU_USER_EXIT(r3, r4)2:#endif	ld	r3,_CCR(r1)	ld	r4,_LINK(r1)	ld	r5,_CTR(r1)	ld	r6,_XER(r1)	mtcr	r3	mtlr	r4	mtctr	r5	mtxer	r6	REST_GPR(0, r1)	REST_8GPRS(2, r1)	mfmsr	r10	rldicl	r10,r10,48,1		/* clear EE */	rldicr	r10,r10,16,61		/* clear RI (LE is 0 already) */	mtmsrd	r10,1	mtspr	SPRN_SRR1,r12	mtspr	SPRN_SRR0,r11	REST_4GPRS(10, r1)	ld	r1,GPR1(r1)	rfid	b	.	/* prevent speculative execution */unrecov_fer:	bl	.save_nvgprs1:	addi	r3,r1,STACK_FRAME_OVERHEAD	bl	.unrecoverable_exception	b	1b/* * Here r13 points to the paca, r9 contains the saved CR, * SRR0 and SRR1 are saved in r11 and r12, * r9 - r13 are saved in paca->exgen. */	.align	7	.globl data_access_commondata_access_common:	mfspr	r10,SPRN_DAR	std	r10,PACA_EXGEN+EX_DAR(r13)	mfspr	r10,SPRN_DSISR	stw	r10,PACA_EXGEN+EX_DSISR(r13)	EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN)	ld	r3,PACA_EXGEN+EX_DAR(r13)	lwz	r4,PACA_EXGEN+EX_DSISR(r13)	li	r5,0x300

⌨️ 快捷键说明

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