1049 lines · 26.1 KB · Assembly
RawDownload
/* SPDX-License-Identifier: GPL-2.0-or-later *//* *  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 entry point for the 64-bit kernel along *  with some early initialization code common to all 64-bit powerpc *  variants. */ #include <linux/linkage.h>#include <linux/threads.h>#include <linux/init.h>#include <asm/reg.h>#include <asm/page.h>#include <asm/mmu.h>#include <asm/ppc_asm.h>#include <asm/head-64.h>#include <asm/asm-offsets.h>#include <asm/bug.h>#include <asm/cputable.h>#include <asm/setup.h>#include <asm/hvcall.h>#include <asm/thread_info.h>#include <asm/firmware.h>#include <asm/page_64.h>#include <asm/irqflags.h>#include <asm/kvm_book3s_asm.h>#include <asm/ptrace.h>#include <asm/hw_irq.h>#include <asm/cputhreads.h>#include <asm/ppc-opcode.h>#include <asm/feature-fixups.h>#ifdef CONFIG_PPC_BOOK3S#include <asm/exception-64s.h>#else#include <asm/exception-64e.h>#endif /* The physical memory is laid out such that the secondary processor * spin code sits at 0x0000...0x00ff. On server, the vectors follow * using the layout described in exceptions-64s.S */ /* * Entering into this code we make the following assumptions: * *  For pSeries or server processors: *   1. The MMU is off & open firmware is running in real mode. *   2. The primary CPU enters at __start. *   3. If the RTAS supports "query-cpu-stopped-state", then secondary *      CPUs will enter as directed by "start-cpu" RTAS call, which is *      generic_secondary_smp_init, with PIR in r3. *   4. Else the secondary CPUs will enter at secondary_hold (0x60) as *      directed by the "start-cpu" RTS call, with PIR in r3. * -or- For OPAL entry: *   1. The MMU is off, processor in HV mode. *   2. The primary CPU enters at 0 with device-tree in r3, OPAL base *      in r8, and entry in r9 for debugging purposes. *   3. Secondary CPUs enter as directed by OPAL_START_CPU call, which *      is at generic_secondary_smp_init, with PIR in r3. * *  For Book3E processors: *   1. The MMU is on running in AS0 in a state defined in ePAPR *   2. The kernel is entered at __start */ /* * boot_from_prom and prom_init run at the physical address. Everything * after prom and kexec entry run at the virtual address (PAGE_OFFSET). * Secondaries run at the virtual address from generic_secondary_common_init * onward. */ OPEN_FIXED_SECTION(first_256B, 0x0, 0x100)USE_FIXED_SECTION(first_256B)	/*	 * Offsets are relative from the start of fixed section, and	 * first_256B starts at 0. Offsets are a bit easier to use here	 * than the fixed section entry macros.	 */	. = 0x0_GLOBAL(__start)	/* NOP this out unconditionally */BEGIN_FTR_SECTION	FIXUP_ENDIAN	b	__start_initialization_multiplatformEND_FTR_SECTION(0, 1) 	/* Catch branch to 0 in real mode */	trap 	/* Secondary processors spin on this value until it becomes non-zero.	 * When non-zero, it contains the real address of the function the cpu	 * should jump to.	 */	.balign 8	.globl  __secondary_hold_spinloop__secondary_hold_spinloop:	.8byte	0x0 	/* Secondary processors write this value with their cpu # */	/* after they enter the spin loop immediately below.	  */	.globl	__secondary_hold_acknowledge__secondary_hold_acknowledge:	.8byte	0x0 #ifdef CONFIG_RELOCATABLE	/* This flag is set to 1 by a loader if the kernel should run	 * at the loaded address instead of the linked address.  This	 * is used by kexec-tools to keep the kdump kernel in the	 * crash_kernel region.  The loader is responsible for	 * observing the alignment requirement.	 */ #ifdef CONFIG_RELOCATABLE_TEST#define RUN_AT_LOAD_DEFAULT 1		/* Test relocation, do not copy to 0 */#else#define RUN_AT_LOAD_DEFAULT 0x72756e30  /* "run0" -- relocate to 0 by default */#endif 	/* Do not move this variable as kexec-tools knows about it. */	. = 0x5c	.globl	__run_at_load__run_at_load:DEFINE_FIXED_SYMBOL(__run_at_load, first_256B)	.long	RUN_AT_LOAD_DEFAULT#endif 	. = 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. * Use .globl here not _GLOBAL because we want __secondary_hold * to be the actual text address, not a descriptor. */	.globl	__secondary_hold__secondary_hold:	FIXUP_ENDIAN#ifndef CONFIG_PPC_BOOK3E_64	mfmsr	r24	ori	r24,r24,MSR_RI	mtmsrd	r24			/* RI on */#endif	/* Grab our physical cpu number */	mr	r24,r3	/* stash r4 for book3e */	mr	r25,r4 	/* 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,(ABS_ADDR(__secondary_hold_acknowledge, first_256B))(0)	sync 	/* All secondary cpus wait here until told to start. */100:	ld	r12,(ABS_ADDR(__secondary_hold_spinloop, first_256B))(0)	cmpdi	0,r12,0	beq	100b #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC_CORE)#ifdef CONFIG_PPC_BOOK3E_64	tovirt(r12,r12)#endif	mtctr	r12	mr	r3,r24	/*	 * it may be the case that other platforms have r4 right to	 * begin with, this gives us some safety in case it is not	 */#ifdef CONFIG_PPC_BOOK3E_64	mr	r4,r25#else	li	r4,0#endif	/* Make sure that patched code is visible */	isync	bctr#else0:	trap	EMIT_BUG_ENTRY 0b, __FILE__, __LINE__, 0#endifCLOSE_FIXED_SECTION(first_256B) /* * On server, we include the exception vectors code here as it * relies on absolute addressing which is only possible within * this compilation unit */#ifdef CONFIG_PPC_BOOK3S#include "exceptions-64s.S"#elseOPEN_TEXT_SECTION(0x100)#endif USE_TEXT_SECTION() #include "interrupt_64.S" #ifdef CONFIG_PPC_BOOK3E_64/* * The booting_thread_hwid holds the thread id we want to boot in cpu * hotplug case. It is set by cpu hotplug code, and is invalid by default. * The thread id is the same as the initial value of SPRN_PIR[THREAD_ID] * bit field. */	.globl	booting_thread_hwidbooting_thread_hwid:	.long  INVALID_THREAD_HWID	.align 3/* * start a thread in the same core * input parameters: * r3 = the thread physical id * r4 = the entry point where thread starts */_GLOBAL(book3e_start_thread)	LOAD_REG_IMMEDIATE(r5, MSR_KERNEL)	cmpwi	r3, 0	beq	10f	cmpwi	r3, 1	beq	11f	/* If the thread id is invalid, just exit. */	b	13f10:	MTTMR(TMRN_IMSR0, 5)	MTTMR(TMRN_INIA0, 4)	b	12f11:	MTTMR(TMRN_IMSR1, 5)	MTTMR(TMRN_INIA1, 4)12:	isync	li	r6, 1	sld	r6, r6, r3	mtspr	SPRN_TENS, r613:	blr /* * stop a thread in the same core * input parameter: * r3 = the thread physical id */_GLOBAL(book3e_stop_thread)	cmpwi	r3, 0	beq	10f	cmpwi	r3, 1	beq	10f	/* If the thread id is invalid, just exit. */	b	13f10:	li	r4, 1	sld	r4, r4, r3	mtspr	SPRN_TENC, r413:	blr _GLOBAL(fsl_secondary_thread_init)	mfspr	r4,SPRN_BUCSR 	/* Enable branch prediction */	lis     r3,BUCSR_INIT@h	ori     r3,r3,BUCSR_INIT@l	mtspr   SPRN_BUCSR,r3	isync 	/*	 * Fix PIR to match the linear numbering in the device tree.	 *	 * On e6500, the reset value of PIR uses the low three bits for	 * the thread within a core, and the upper bits for the core	 * number.  There are two threads per core, so shift everything	 * but the low bit right by two bits so that the cpu numbering is	 * continuous.	 *	 * If the old value of BUCSR is non-zero, this thread has run	 * before.  Thus, we assume we are coming from kexec or a similar	 * scenario, and PIR is already set to the correct value.  This	 * is a bit of a hack, but there are limited opportunities for	 * getting information into the thread and the alternatives	 * seemed like they'd be overkill.  We can't tell just by looking	 * at the old PIR value which state it's in, since the same value	 * could be valid for one thread out of reset and for a different	 * thread in Linux.	 */ 	mfspr	r3, SPRN_PIR	cmpwi	r4,0	bne	1f	rlwimi	r3, r3, 30, 2, 30	mtspr	SPRN_PIR, r31:	mr	r24,r3 	/* turn on 64-bit mode */	bl	enable_64b_mode 	/* Book3E initialization */	mr	r3,r24	bl	book3e_secondary_thread_init	bl	relative_toc 	b	generic_secondary_common_init #endif /* CONFIG_PPC_BOOK3E_64 */ /* * On pSeries and most other platforms, secondary processors spin * in the following code. * At entry, r3 = this processor's number (physical cpu id) * * On Book3E, r4 = 1 to indicate that the initial TLB entry for * this core already exists (setup via some other mechanism such * as SCOM before entry). */_GLOBAL(generic_secondary_smp_init)	FIXUP_ENDIAN 	li	r13,0 	/* Poison TOC */	li	r2,-1 	mr	r24,r3	mr	r25,r4 	/* turn on 64-bit mode */	bl	enable_64b_mode #ifdef CONFIG_PPC_BOOK3E_64	/* Book3E initialization */	mr	r3,r24	mr	r4,r25	bl	book3e_secondary_core_init	/* Now NIA and r2 are relocated to PAGE_OFFSET if not already *//* * After common core init has finished, check if the current thread is the * one we wanted to boot. If not, start the specified thread and stop the * current thread. */	LOAD_REG_ADDR(r4, booting_thread_hwid)	lwz     r3, 0(r4)	li	r5, INVALID_THREAD_HWID	cmpw	r3, r5	beq	20f 	/*	 * The value of booting_thread_hwid has been stored in r3,	 * so make it invalid.	 */	stw	r5, 0(r4) 	/*	 * Get the current thread id and check if it is the one we wanted.	 * If not, start the one specified in booting_thread_hwid and stop	 * the current thread.	 */	mfspr	r8, SPRN_TIR	cmpw	r3, r8	beq	20f 	/* start the specified thread */	LOAD_REG_ADDR(r5, DOTSYM(fsl_secondary_thread_init))	bl	book3e_start_thread 	/* stop the current thread */	mr	r3, r8	bl	book3e_stop_thread10:	b	10b20:#else	/* Now the MMU is off, can branch to our PAGE_OFFSET address */	bcl	20,31,$+41:	mflr	r11	addi	r11,r11,(2f - 1b)	tovirt(r11, r11)	mtctr	r11	bctr2:	bl	relative_toc#endif generic_secondary_common_init:	/* Set up a paca value for this processor. Since we have the	 * physical cpu id in r24, we need to search the pacas to find	 * which logical id maps to our physical one.	 */#ifndef CONFIG_SMP	b	kexec_wait		/* wait for next kernel if !SMP	 */#else	LOAD_REG_ADDR(r8, paca_ptrs)	/* Load paca_ptrs pointe	 */	ld	r8,0(r8)		/* Get base vaddr of array	 */#if (NR_CPUS == 1) || defined(CONFIG_FORCE_NR_CPUS)	LOAD_REG_IMMEDIATE(r7, NR_CPUS)#else	LOAD_REG_ADDR(r7, nr_cpu_ids)	/* Load nr_cpu_ids address       */	lwz	r7,0(r7)		/* also the max paca allocated 	 */#endif	li	r5,0			/* logical cpu id                */1:	sldi	r9,r5,3			/* get paca_ptrs[] index from cpu id */	ldx	r13,r9,r8		/* r13 = paca_ptrs[cpu id]       */	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */	cmpw	r6,r24			/* Compare to our id             */	beq	2f	addi	r5,r5,1	cmpw	r5,r7			/* Check if more pacas exist     */	blt	1b 	mr	r3,r24			/* not found, copy phys to r3	 */	b	kexec_wait		/* next kernel might do better	 */ 2:	SET_PACA(r13)#ifdef CONFIG_PPC_BOOK3E_64	addi	r12,r13,PACA_EXTLB	/* and TLB exc frame in another  */	mtspr	SPRN_SPRG_TLB_EXFRAME,r12#endif 	/* From now on, r24 is expected to be logical cpuid */	mr	r24,r5 	/* Create a temp kernel stack for use before relocation is on.	*/	ld	r1,PACAEMERGSP(r13)	subi	r1,r1,STACK_FRAME_MIN_SIZE 	/* See if we need to call a cpu state restore handler */	LOAD_REG_ADDR(r23, cur_cpu_spec)	ld	r23,0(r23)	ld	r12,CPU_SPEC_RESTORE(r23)	cmpdi	0,r12,0	beq	3f#ifdef CONFIG_PPC64_ELF_ABI_V1	ld	r12,0(r12)#endif	mtctr	r12	bctrl 3:	LOAD_REG_ADDR(r3, spinning_secondaries) /* Decrement spinning_secondaries */	lwarx	r4,0,r3	subi	r4,r4,1	stwcx.	r4,0,r3	bne	3b	isync 4:	HMT_LOW	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor should */					/* start.			 */	cmpwi	0,r23,0	beq	4b			/* Loop until told to go	 */ 	sync				/* order paca.run and cur_cpu_spec */	isync				/* In case code patching happened */ 	b	__secondary_start#endif /* SMP */ /* * Turn the MMU off. * Assumes we're mapped EA == RA if the MMU is on. */#ifdef CONFIG_PPC_BOOK3SSYM_FUNC_START_LOCAL(__mmu_off)	mfmsr	r3	andi.	r0,r3,MSR_IR|MSR_DR	beqlr	mflr	r4	andc	r3,r3,r0	mtspr	SPRN_SRR0,r4	mtspr	SPRN_SRR1,r3	sync	rfid	b	.	/* prevent speculative execution */SYM_FUNC_END(__mmu_off) SYM_FUNC_START_LOCAL(start_initialization_book3s)	mflr	r25 	/* Setup some critical 970 SPRs before switching MMU off */	mfspr	r0,SPRN_PVR	srwi	r0,r0,16	cmpwi	r0,0x39		/* 970 */	beq	1f	cmpwi	r0,0x3c		/* 970FX */	beq	1f	cmpwi	r0,0x44		/* 970MP */

Lines 1–500 of 1049.

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