Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0-or-later */
0002 
0003 #include <asm/asm-offsets.h>
0004 #include <asm/bug.h>
0005 #include <asm/page.h>
0006 #include <asm/ppc_asm.h>
0007 
0008 /*
0009  * RTAS is called with MSR IR, DR, EE disabled, and LR in the return address.
0010  *
0011  * Note: r3 is an input parameter to rtas, so don't trash it...
0012  */
0013 
0014 #ifdef CONFIG_PPC32
0015 _GLOBAL(enter_rtas)
0016     stwu    r1,-INT_FRAME_SIZE(r1)
0017     mflr    r0
0018     stw r0,INT_FRAME_SIZE+4(r1)
0019     LOAD_REG_ADDR(r4, rtas)
0020     lis r6,1f@ha    /* physical return address for rtas */
0021     addi    r6,r6,1f@l
0022     tophys(r6,r6)
0023     lwz r8,RTASENTRY(r4)
0024     lwz r4,RTASBASE(r4)
0025     mfmsr   r9
0026     stw r9,8(r1)
0027     li  r9,MSR_KERNEL & ~(MSR_IR|MSR_DR)
0028     mtlr    r6
0029     stw r1, THREAD + RTAS_SP(r2)
0030     mtspr   SPRN_SRR0,r8
0031     mtspr   SPRN_SRR1,r9
0032     rfi
0033 1:
0034     lis r8, 1f@h
0035     ori r8, r8, 1f@l
0036     LOAD_REG_IMMEDIATE(r9,MSR_KERNEL)
0037     mtspr   SPRN_SRR0,r8
0038     mtspr   SPRN_SRR1,r9
0039     rfi         /* Reactivate MMU translation */
0040 1:
0041     lwz r8,INT_FRAME_SIZE+4(r1) /* get return address */
0042     lwz r9,8(r1)    /* original msr value */
0043     addi    r1,r1,INT_FRAME_SIZE
0044     li  r0,0
0045     stw r0, THREAD + RTAS_SP(r2)
0046     mtlr    r8
0047     mtmsr   r9
0048     blr         /* return to caller */
0049 _ASM_NOKPROBE_SYMBOL(enter_rtas)
0050 
0051 #else /* CONFIG_PPC32 */
0052 #include <asm/exception-64s.h>
0053 
0054 /*
0055  * 32-bit rtas on 64-bit machines has the additional problem that RTAS may
0056  * not preserve the upper parts of registers it uses.
0057  */
0058 _GLOBAL(enter_rtas)
0059     mflr    r0
0060     std r0,16(r1)
0061     stdu    r1,-SWITCH_FRAME_SIZE(r1) /* Save SP and create stack space. */
0062 
0063     /* Because RTAS is running in 32b mode, it clobbers the high order half
0064      * of all registers that it saves.  We therefore save those registers
0065      * RTAS might touch to the stack.  (r0, r3-r12 are caller saved)
0066      */
0067     SAVE_GPR(2, r1)         /* Save the TOC */
0068     SAVE_NVGPRS(r1)         /* Save the non-volatiles */
0069 
0070     mfcr    r4
0071     std r4,_CCR(r1)
0072     mfctr   r5
0073     std r5,_CTR(r1)
0074     mfspr   r6,SPRN_XER
0075     std r6,_XER(r1)
0076     mfdar   r7
0077     std r7,_DAR(r1)
0078     mfdsisr r8
0079     std r8,_DSISR(r1)
0080 
0081     /* Temporary workaround to clear CR until RTAS can be modified to
0082      * ignore all bits.
0083      */
0084     li  r0,0
0085     mtcr    r0
0086 
0087     mfmsr   r6
0088 
0089     /* Unfortunately, the stack pointer and the MSR are also clobbered,
0090      * so they are saved in the PACA which allows us to restore
0091      * our original state after RTAS returns.
0092      */
0093     std r1,PACAR1(r13)
0094     std r6,PACASAVEDMSR(r13)
0095 
0096     /* Setup our real return addr */
0097     LOAD_REG_ADDR(r4,rtas_return_loc)
0098     clrldi  r4,r4,2         /* convert to realmode address */
0099     mtlr    r4
0100 
0101 __enter_rtas:
0102     LOAD_REG_ADDR(r4, rtas)
0103     ld  r5,RTASENTRY(r4)    /* get the rtas->entry value */
0104     ld  r4,RTASBASE(r4)     /* get the rtas->base value */
0105 
0106     /*
0107      * RTAS runs in 32-bit big endian real mode, but leave MSR[RI] on as we
0108      * may hit NMI (SRESET or MCE) while in RTAS. RTAS should disable RI in
0109      * its critical regions (as specified in PAPR+ section 7.2.1). MSR[S]
0110      * is not impacted by RFI_TO_KERNEL (only urfid can unset it). So if
0111      * MSR[S] is set, it will remain when entering RTAS.
0112      * If we're in HV mode, RTAS must also run in HV mode, so extract MSR_HV
0113      * from the saved MSR value and insert into the value RTAS will use.
0114      */
0115     extrdi  r0, r6, 1, 63 - MSR_HV_LG
0116     LOAD_REG_IMMEDIATE(r6, MSR_ME | MSR_RI)
0117     insrdi  r6, r0, 1, 63 - MSR_HV_LG
0118 
0119     li      r0,0
0120     mtmsrd  r0,1                    /* disable RI before using SRR0/1 */
0121     
0122     mtspr   SPRN_SRR0,r5
0123     mtspr   SPRN_SRR1,r6
0124     RFI_TO_KERNEL
0125     b   .   /* prevent speculative execution */
0126 rtas_return_loc:
0127     FIXUP_ENDIAN
0128 
0129     /* Set SF before anything. */
0130     LOAD_REG_IMMEDIATE(r6, MSR_KERNEL & ~(MSR_IR|MSR_DR))
0131     mtmsrd  r6
0132 
0133     /* relocation is off at this point */
0134     GET_PACA(r13)
0135 
0136     bcl 20,31,$+4
0137 0:  mflr    r3
0138     ld  r3,(1f-0b)(r3)      /* get &rtas_restore_regs */
0139 
0140     ld  r1,PACAR1(r13)      /* Restore our SP */
0141     ld  r4,PACASAVEDMSR(r13)    /* Restore our MSR */
0142 
0143     mtspr   SPRN_SRR0,r3
0144     mtspr   SPRN_SRR1,r4
0145     RFI_TO_KERNEL
0146     b   .   /* prevent speculative execution */
0147 _ASM_NOKPROBE_SYMBOL(enter_rtas)
0148 _ASM_NOKPROBE_SYMBOL(__enter_rtas)
0149 _ASM_NOKPROBE_SYMBOL(rtas_return_loc)
0150 
0151     .align  3
0152 1:  .8byte  rtas_restore_regs
0153 
0154 rtas_restore_regs:
0155     /* relocation is on at this point */
0156     REST_GPR(2, r1)         /* Restore the TOC */
0157     REST_NVGPRS(r1)         /* Restore the non-volatiles */
0158 
0159     ld  r4,_CCR(r1)
0160     mtcr    r4
0161     ld  r5,_CTR(r1)
0162     mtctr   r5
0163     ld  r6,_XER(r1)
0164     mtspr   SPRN_XER,r6
0165     ld  r7,_DAR(r1)
0166     mtdar   r7
0167     ld  r8,_DSISR(r1)
0168     mtdsisr r8
0169 
0170     addi    r1,r1,SWITCH_FRAME_SIZE /* Unstack our frame */
0171     ld  r0,16(r1)       /* get return address */
0172 
0173     mtlr    r0
0174     blr             /* return to caller */
0175 
0176 #endif /* CONFIG_PPC32 */