Linux Audio

Check our new training course

Loading...
  1/* SPDX-License-Identifier: GPL-2.0-or-later */
  2
  3#include <asm/asm-offsets.h>
  4#include <asm/bug.h>
  5#include <asm/page.h>
  6#include <asm/ppc_asm.h>
  7
  8/*
  9 * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address.
 10 *
 11 * Note: r3 is an input parameter to rtas, so don't trash it...
 12 */
 13
 14#ifdef CONFIG_PPC32
 15_GLOBAL(enter_rtas)
 16	stwu	r1,-INT_FRAME_SIZE(r1)
 17	mflr	r0
 18	stw	r0,INT_FRAME_SIZE+4(r1)
 19	LOAD_REG_ADDR(r4, rtas)
 20	lis	r6,1f@ha	/* physical return address for rtas */
 21	addi	r6,r6,1f@l
 22	tophys(r6,r6)
 23	lwz	r8,RTASENTRY(r4)
 24	lwz	r4,RTASBASE(r4)
 25	mfmsr	r9
 26	stw	r9,8(r1)
 27	li	r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
 28	mtlr	r6
 29	stw	r1, THREAD + RTAS_SP(r2)
 30	mtspr	SPRN_SRR0,r8
 31	mtspr	SPRN_SRR1,r9
 32	rfi
 331:
 34	lis	r8, 1f@h
 35	ori	r8, r8, 1f@l
 36	LOAD_REG_IMMEDIATE(r9,MSR_KERNEL)
 37	mtspr	SPRN_SRR0,r8
 38	mtspr	SPRN_SRR1,r9
 39	rfi			/* Reactivate MMU translation */
 401:
 41	lwz	r8,INT_FRAME_SIZE+4(r1)	/* get return address */
 42	lwz	r9,8(r1)	/* original msr value */
 43	addi	r1,r1,INT_FRAME_SIZE
 44	li	r0,0
 45	stw	r0, THREAD + RTAS_SP(r2)
 46	mtlr	r8
 47	mtmsr	r9
 48	blr			/* return to caller */
 49_ASM_NOKPROBE_SYMBOL(enter_rtas)
 50
 51#else /* CONFIG_PPC32 */
 52#include <asm/exception-64s.h>
 53
 54/*
 55 * 32-bit rtas on 64-bit machines has the additional problem that RTAS may
 56 * not preserve the upper parts of registers it uses.
 57 */
 58_GLOBAL(enter_rtas)
 59	mflr	r0
 60	std	r0,16(r1)
 61	stdu	r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */
 62
 63	/* Because RTAS is running in 32b mode, it clobbers the high order half
 64	 * of all registers that it saves.  We therefore save those registers
 65	 * RTAS might touch to the stack.  (r0, r3-r12 are caller saved)
 66	 */
 67	SAVE_GPR(2, r1)			/* Save the TOC */
 68	SAVE_NVGPRS(r1)			/* Save the non-volatiles */
 69
 70	mfcr	r4
 71	std	r4,_CCR(r1)
 72	mfctr	r5
 73	std	r5,_CTR(r1)
 74	mfspr	r6,SPRN_XER
 75	std	r6,_XER(r1)
 76	mfdar	r7
 77	std	r7,_DAR(r1)
 78	mfdsisr	r8
 79	std	r8,_DSISR(r1)
 80
 81	/* Temporary workaround to clear CR until RTAS can be modified to
 82	 * ignore all bits.
 83	 */
 84	li	r0,0
 85	mtcr	r0
 86
 87	mfmsr	r6
 88
 89	/* Unfortunately, the stack pointer and the MSR are also clobbered,
 90	 * so they are saved in the PACA which allows us to restore
 91	 * our original state after RTAS returns.
 92	 */
 93	std	r1,PACAR1(r13)
 94	std	r6,PACASAVEDMSR(r13)
 95
 96	/* Setup our real return addr */
 97	LOAD_REG_ADDR(r4,rtas_return_loc)
 98	clrldi	r4,r4,2			/* convert to realmode address */
 99	mtlr	r4
100
101__enter_rtas:
102	LOAD_REG_ADDR(r4, rtas)
103	ld	r5,RTASENTRY(r4)	/* get the rtas->entry value */
104	ld	r4,RTASBASE(r4)		/* get the rtas->base value */
105
106	/*
107	 * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we
108	 * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in
109	 * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
110	 * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
111	 * MSR[S] is set, it will remain when entering RTAS.
112	 * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
113	 * from the saved MSR value and insert into the value RTAS will use.
114	 */
115	extrdi	r0, r6, 1, 63 - MSR_HV_LG
116	LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
117	insrdi	r6, r0, 1, 63 - MSR_HV_LG
118
119	li      r0,0
120	mtmsrd  r0,1                    /* disable RI before using SRR0/1 */
121	
122	mtspr	SPRN_SRR0,r5
123	mtspr	SPRN_SRR1,r6
124	RFI_TO_KERNEL
125	b	.	/* prevent speculative execution */
126rtas_return_loc:
127	FIXUP_ENDIAN
128
129	/* Set SF before anything. */
130	LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR))
131	mtmsrd	r6
132
133	/* relocation is off at this point */
134	GET_PACA(r13)
135
136	bcl	20,31,$+4
1370:	mflr	r3
138	ld	r3,(1f-0b)(r3)		/* get &rtas_restore_regs */
139
140	ld	r1,PACAR1(r13)		/* Restore our SP */
141	ld	r4,PACASAVEDMSR(r13)	/* Restore our MSR */
142
143	mtspr	SPRN_SRR0,r3
144	mtspr	SPRN_SRR1,r4
145	RFI_TO_KERNEL
146	b	.	/* prevent speculative execution */
147_ASM_NOKPROBE_SYMBOL(enter_rtas)
148_ASM_NOKPROBE_SYMBOL(__enter_rtas)
149_ASM_NOKPROBE_SYMBOL(rtas_return_loc)
150
151	.align	3
1521:	.8byte	rtas_restore_regs
153
154rtas_restore_regs:
155	/* relocation is on at this point */
156	REST_GPR(2, r1)			/* Restore the TOC */
157	REST_NVGPRS(r1)			/* Restore the non-volatiles */
158
159	ld	r4,_CCR(r1)
160	mtcr	r4
161	ld	r5,_CTR(r1)
162	mtctr	r5
163	ld	r6,_XER(r1)
164	mtspr	SPRN_XER,r6
165	ld	r7,_DAR(r1)
166	mtdar	r7
167	ld	r8,_DSISR(r1)
168	mtdsisr	r8
169
170	addi	r1,r1,SWITCH_FRAME_SIZE	/* Unstack our frame */
171	ld	r0,16(r1)		/* get return address */
172
173	mtlr	r0
174	blr				/* return to caller */
175
176#endif /* CONFIG_PPC32 */