Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #include <linux/threads.h>
0003 #include <asm/processor.h>
0004 #include <asm/page.h>
0005 #include <asm/cputable.h>
0006 #include <asm/thread_info.h>
0007 #include <asm/ppc_asm.h>
0008 #include <asm/asm-offsets.h>
0009 #include <asm/mmu.h>
0010 #include <asm/feature-fixups.h>
0011 
0012 /*
0013  * Structure for storing CPU registers on the save area.
0014  */
0015 #define SL_SP       0
0016 #define SL_PC       4
0017 #define SL_MSR      8
0018 #define SL_SDR1     0xc
0019 #define SL_SPRG0    0x10    /* 4 sprg's */
0020 #define SL_DBAT0    0x20
0021 #define SL_IBAT0    0x28
0022 #define SL_DBAT1    0x30
0023 #define SL_IBAT1    0x38
0024 #define SL_DBAT2    0x40
0025 #define SL_IBAT2    0x48
0026 #define SL_DBAT3    0x50
0027 #define SL_IBAT3    0x58
0028 #define SL_DBAT4    0x60
0029 #define SL_IBAT4    0x68
0030 #define SL_DBAT5    0x70
0031 #define SL_IBAT5    0x78
0032 #define SL_DBAT6    0x80
0033 #define SL_IBAT6    0x88
0034 #define SL_DBAT7    0x90
0035 #define SL_IBAT7    0x98
0036 #define SL_TB       0xa0
0037 #define SL_R2       0xa8
0038 #define SL_CR       0xac
0039 #define SL_LR       0xb0
0040 #define SL_R12      0xb4    /* r12 to r31 */
0041 #define SL_SIZE     (SL_R12 + 80)
0042 
0043     .section .data
0044     .align  5
0045 
0046 _GLOBAL(swsusp_save_area)
0047     .space  SL_SIZE
0048 
0049 
0050     .section .text
0051     .align  5
0052 
0053 _GLOBAL(swsusp_arch_suspend)
0054 
0055     lis r11,swsusp_save_area@h
0056     ori r11,r11,swsusp_save_area@l
0057 
0058     mflr    r0
0059     stw r0,SL_LR(r11)
0060     mfcr    r0
0061     stw r0,SL_CR(r11)
0062     stw r1,SL_SP(r11)
0063     stw r2,SL_R2(r11)
0064     stmw    r12,SL_R12(r11)
0065 
0066     /* Save MSR & SDR1 */
0067     mfmsr   r4
0068     stw r4,SL_MSR(r11)
0069     mfsdr1  r4
0070     stw r4,SL_SDR1(r11)
0071 
0072     /* Get a stable timebase and save it */
0073 1:  mftbu   r4
0074     stw r4,SL_TB(r11)
0075     mftb    r5
0076     stw r5,SL_TB+4(r11)
0077     mftbu   r3
0078     cmpw    r3,r4
0079     bne 1b
0080 
0081     /* Save SPRGs */
0082     mfsprg  r4,0
0083     stw r4,SL_SPRG0(r11)
0084     mfsprg  r4,1
0085     stw r4,SL_SPRG0+4(r11)
0086     mfsprg  r4,2
0087     stw r4,SL_SPRG0+8(r11)
0088     mfsprg  r4,3
0089     stw r4,SL_SPRG0+12(r11)
0090 
0091     /* Save BATs */
0092     mfdbatu r4,0
0093     stw r4,SL_DBAT0(r11)
0094     mfdbatl r4,0
0095     stw r4,SL_DBAT0+4(r11)
0096     mfdbatu r4,1
0097     stw r4,SL_DBAT1(r11)
0098     mfdbatl r4,1
0099     stw r4,SL_DBAT1+4(r11)
0100     mfdbatu r4,2
0101     stw r4,SL_DBAT2(r11)
0102     mfdbatl r4,2
0103     stw r4,SL_DBAT2+4(r11)
0104     mfdbatu r4,3
0105     stw r4,SL_DBAT3(r11)
0106     mfdbatl r4,3
0107     stw r4,SL_DBAT3+4(r11)
0108     mfibatu r4,0
0109     stw r4,SL_IBAT0(r11)
0110     mfibatl r4,0
0111     stw r4,SL_IBAT0+4(r11)
0112     mfibatu r4,1
0113     stw r4,SL_IBAT1(r11)
0114     mfibatl r4,1
0115     stw r4,SL_IBAT1+4(r11)
0116     mfibatu r4,2
0117     stw r4,SL_IBAT2(r11)
0118     mfibatl r4,2
0119     stw r4,SL_IBAT2+4(r11)
0120     mfibatu r4,3
0121     stw r4,SL_IBAT3(r11)
0122     mfibatl r4,3
0123     stw r4,SL_IBAT3+4(r11)
0124 
0125 BEGIN_MMU_FTR_SECTION
0126     mfspr   r4,SPRN_DBAT4U
0127     stw r4,SL_DBAT4(r11)
0128     mfspr   r4,SPRN_DBAT4L
0129     stw r4,SL_DBAT4+4(r11)
0130     mfspr   r4,SPRN_DBAT5U
0131     stw r4,SL_DBAT5(r11)
0132     mfspr   r4,SPRN_DBAT5L
0133     stw r4,SL_DBAT5+4(r11)
0134     mfspr   r4,SPRN_DBAT6U
0135     stw r4,SL_DBAT6(r11)
0136     mfspr   r4,SPRN_DBAT6L
0137     stw r4,SL_DBAT6+4(r11)
0138     mfspr   r4,SPRN_DBAT7U
0139     stw r4,SL_DBAT7(r11)
0140     mfspr   r4,SPRN_DBAT7L
0141     stw r4,SL_DBAT7+4(r11)
0142     mfspr   r4,SPRN_IBAT4U
0143     stw r4,SL_IBAT4(r11)
0144     mfspr   r4,SPRN_IBAT4L
0145     stw r4,SL_IBAT4+4(r11)
0146     mfspr   r4,SPRN_IBAT5U
0147     stw r4,SL_IBAT5(r11)
0148     mfspr   r4,SPRN_IBAT5L
0149     stw r4,SL_IBAT5+4(r11)
0150     mfspr   r4,SPRN_IBAT6U
0151     stw r4,SL_IBAT6(r11)
0152     mfspr   r4,SPRN_IBAT6L
0153     stw r4,SL_IBAT6+4(r11)
0154     mfspr   r4,SPRN_IBAT7U
0155     stw r4,SL_IBAT7(r11)
0156     mfspr   r4,SPRN_IBAT7L
0157     stw r4,SL_IBAT7+4(r11)
0158 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
0159 
0160 #if  0
0161     /* Backup various CPU config stuffs */
0162     bl  __save_cpu_setup
0163 #endif
0164     /* Call the low level suspend stuff (we should probably have made
0165      * a stackframe...
0166      */
0167     bl  swsusp_save
0168 
0169     /* Restore LR from the save area */
0170     lis r11,swsusp_save_area@h
0171     ori r11,r11,swsusp_save_area@l
0172     lwz r0,SL_LR(r11)
0173     mtlr    r0
0174 
0175     blr
0176 
0177 
0178 /* Resume code */
0179 _GLOBAL(swsusp_arch_resume)
0180 
0181 #ifdef CONFIG_ALTIVEC
0182     /* Stop pending alitvec streams and memory accesses */
0183 BEGIN_FTR_SECTION
0184     PPC_DSSALL
0185 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
0186 #endif
0187     sync
0188 
0189     /* Disable MSR:DR to make sure we don't take a TLB or
0190      * hash miss during the copy, as our hash table will
0191      * for a while be unusable. For .text, we assume we are
0192      * covered by a BAT. This works only for non-G5 at this
0193      * point. G5 will need a better approach, possibly using
0194      * a small temporary hash table filled with large mappings,
0195      * disabling the MMU completely isn't a good option for
0196      * performance reasons.
0197      * (Note that 750's may have the same performance issue as
0198      * the G5 in this case, we should investigate using moving
0199      * BATs for these CPUs)
0200      */
0201     mfmsr   r0
0202     sync
0203     rlwinm  r0,r0,0,28,26       /* clear MSR_DR */
0204     mtmsr   r0
0205     sync
0206     isync
0207 
0208     /* Load ptr the list of pages to copy in r3 */
0209     lis r11,(restore_pblist - KERNELBASE)@h
0210     ori r11,r11,restore_pblist@l
0211     lwz r10,0(r11)
0212 
0213     /* Copy the pages. This is a very basic implementation, to
0214      * be replaced by something more cache efficient */
0215 1:
0216     tophys(r3,r10)
0217     li  r0,256
0218     mtctr   r0
0219     lwz r11,pbe_address(r3) /* source */
0220     tophys(r5,r11)
0221     lwz r10,pbe_orig_address(r3)    /* destination */
0222     tophys(r6,r10)
0223 2:
0224     lwz r8,0(r5)
0225     lwz r9,4(r5)
0226     lwz r10,8(r5)
0227     lwz r11,12(r5)
0228     addi    r5,r5,16
0229     stw r8,0(r6)
0230     stw r9,4(r6)
0231     stw r10,8(r6)
0232     stw r11,12(r6)
0233     addi    r6,r6,16
0234     bdnz    2b
0235     lwz     r10,pbe_next(r3)
0236     cmpwi   0,r10,0
0237     bne 1b
0238 
0239     /* Do a very simple cache flush/inval of the L1 to ensure
0240      * coherency of the icache
0241      */
0242     lis r3,0x0002
0243     mtctr   r3
0244     li  r3, 0
0245 1:
0246     lwz r0,0(r3)
0247     addi    r3,r3,0x0020
0248     bdnz    1b
0249     isync
0250     sync
0251 
0252     /* Now flush those cache lines */
0253     lis r3,0x0002
0254     mtctr   r3
0255     li  r3, 0
0256 1:
0257     dcbf    0,r3
0258     addi    r3,r3,0x0020
0259     bdnz    1b
0260     sync
0261 
0262     /* Ok, we are now running with the kernel data of the old
0263      * kernel fully restored. We can get to the save area
0264      * easily now. As for the rest of the code, it assumes the
0265      * loader kernel and the booted one are exactly identical
0266      */
0267     lis r11,swsusp_save_area@h
0268     ori r11,r11,swsusp_save_area@l
0269     tophys(r11,r11)
0270 
0271 #if 0
0272     /* Restore various CPU config stuffs */
0273     bl  __restore_cpu_setup
0274 #endif
0275     /* Restore the BATs, and SDR1.  Then we can turn on the MMU.
0276      * This is a bit hairy as we are running out of those BATs,
0277      * but first, our code is probably in the icache, and we are
0278      * writing the same value to the BAT, so that should be fine,
0279      * though a better solution will have to be found long-term
0280      */
0281     lwz r4,SL_SDR1(r11)
0282     mtsdr1  r4
0283     lwz r4,SL_SPRG0(r11)
0284     mtsprg  0,r4
0285     lwz r4,SL_SPRG0+4(r11)
0286     mtsprg  1,r4
0287     lwz r4,SL_SPRG0+8(r11)
0288     mtsprg  2,r4
0289     lwz r4,SL_SPRG0+12(r11)
0290     mtsprg  3,r4
0291 
0292 #if 0
0293     lwz r4,SL_DBAT0(r11)
0294     mtdbatu 0,r4
0295     lwz r4,SL_DBAT0+4(r11)
0296     mtdbatl 0,r4
0297     lwz r4,SL_DBAT1(r11)
0298     mtdbatu 1,r4
0299     lwz r4,SL_DBAT1+4(r11)
0300     mtdbatl 1,r4
0301     lwz r4,SL_DBAT2(r11)
0302     mtdbatu 2,r4
0303     lwz r4,SL_DBAT2+4(r11)
0304     mtdbatl 2,r4
0305     lwz r4,SL_DBAT3(r11)
0306     mtdbatu 3,r4
0307     lwz r4,SL_DBAT3+4(r11)
0308     mtdbatl 3,r4
0309     lwz r4,SL_IBAT0(r11)
0310     mtibatu 0,r4
0311     lwz r4,SL_IBAT0+4(r11)
0312     mtibatl 0,r4
0313     lwz r4,SL_IBAT1(r11)
0314     mtibatu 1,r4
0315     lwz r4,SL_IBAT1+4(r11)
0316     mtibatl 1,r4
0317     lwz r4,SL_IBAT2(r11)
0318     mtibatu 2,r4
0319     lwz r4,SL_IBAT2+4(r11)
0320     mtibatl 2,r4
0321     lwz r4,SL_IBAT3(r11)
0322     mtibatu 3,r4
0323     lwz r4,SL_IBAT3+4(r11)
0324     mtibatl 3,r4
0325 BEGIN_MMU_FTR_SECTION
0326     lwz r4,SL_DBAT4(r11)
0327     mtspr   SPRN_DBAT4U,r4
0328     lwz r4,SL_DBAT4+4(r11)
0329     mtspr   SPRN_DBAT4L,r4
0330     lwz r4,SL_DBAT5(r11)
0331     mtspr   SPRN_DBAT5U,r4
0332     lwz r4,SL_DBAT5+4(r11)
0333     mtspr   SPRN_DBAT5L,r4
0334     lwz r4,SL_DBAT6(r11)
0335     mtspr   SPRN_DBAT6U,r4
0336     lwz r4,SL_DBAT6+4(r11)
0337     mtspr   SPRN_DBAT6L,r4
0338     lwz r4,SL_DBAT7(r11)
0339     mtspr   SPRN_DBAT7U,r4
0340     lwz r4,SL_DBAT7+4(r11)
0341     mtspr   SPRN_DBAT7L,r4
0342     lwz r4,SL_IBAT4(r11)
0343     mtspr   SPRN_IBAT4U,r4
0344     lwz r4,SL_IBAT4+4(r11)
0345     mtspr   SPRN_IBAT4L,r4
0346     lwz r4,SL_IBAT5(r11)
0347     mtspr   SPRN_IBAT5U,r4
0348     lwz r4,SL_IBAT5+4(r11)
0349     mtspr   SPRN_IBAT5L,r4
0350     lwz r4,SL_IBAT6(r11)
0351     mtspr   SPRN_IBAT6U,r4
0352     lwz r4,SL_IBAT6+4(r11)
0353     mtspr   SPRN_IBAT6L,r4
0354     lwz r4,SL_IBAT7(r11)
0355     mtspr   SPRN_IBAT7U,r4
0356     lwz r4,SL_IBAT7+4(r11)
0357     mtspr   SPRN_IBAT7L,r4
0358 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
0359 #endif
0360 
0361     /* Flush all TLBs */
0362     lis r4,0x1000
0363 1:  addic.  r4,r4,-0x1000
0364     tlbie   r4
0365     bgt 1b
0366     sync
0367 
0368     /* restore the MSR and turn on the MMU */
0369     lwz r3,SL_MSR(r11)
0370     bl  turn_on_mmu
0371     tovirt(r11,r11)
0372 
0373     /* Restore TB */
0374     li  r3,0
0375     mttbl   r3
0376     lwz r3,SL_TB(r11)
0377     lwz r4,SL_TB+4(r11)
0378     mttbu   r3
0379     mttbl   r4
0380 
0381     /* Kick decrementer */
0382     li  r0,1
0383     mtdec   r0
0384 
0385     /* Restore the callee-saved registers and return */
0386     lwz r0,SL_CR(r11)
0387     mtcr    r0
0388     lwz r2,SL_R2(r11)
0389     lmw r12,SL_R12(r11)
0390     lwz r1,SL_SP(r11)
0391     lwz r0,SL_LR(r11)
0392     mtlr    r0
0393 
0394     // XXX Note: we don't really need to call swsusp_resume
0395 
0396     li  r3,0
0397     blr
0398 _ASM_NOKPROBE_SYMBOL(swsusp_arch_resume)
0399 
0400 /* FIXME:This construct is actually not useful since we don't shut
0401  * down the instruction MMU, we could just flip back MSR-DR on.
0402  */
0403 turn_on_mmu:
0404     mflr    r4
0405     mtsrr0  r4
0406     mtsrr1  r3
0407     sync
0408     isync
0409     rfi
0410 _ASM_NOKPROBE_SYMBOL(turn_on_mmu)
0411