root/arch/powerpc/kernel/swsusp_32.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /* SPDX-License-Identifier: GPL-2.0 */
   2 #include <linux/threads.h>
   3 #include <asm/processor.h>
   4 #include <asm/page.h>
   5 #include <asm/cputable.h>
   6 #include <asm/thread_info.h>
   7 #include <asm/ppc_asm.h>
   8 #include <asm/asm-offsets.h>
   9 #include <asm/mmu.h>
  10 #include <asm/feature-fixups.h>
  11 
  12 /*
  13  * Structure for storing CPU registers on the save area.
  14  */
  15 #define SL_SP           0
  16 #define SL_PC           4
  17 #define SL_MSR          8
  18 #define SL_SDR1         0xc
  19 #define SL_SPRG0        0x10    /* 4 sprg's */
  20 #define SL_DBAT0        0x20
  21 #define SL_IBAT0        0x28
  22 #define SL_DBAT1        0x30
  23 #define SL_IBAT1        0x38
  24 #define SL_DBAT2        0x40
  25 #define SL_IBAT2        0x48
  26 #define SL_DBAT3        0x50
  27 #define SL_IBAT3        0x58
  28 #define SL_DBAT4        0x60
  29 #define SL_IBAT4        0x68
  30 #define SL_DBAT5        0x70
  31 #define SL_IBAT5        0x78
  32 #define SL_DBAT6        0x80
  33 #define SL_IBAT6        0x88
  34 #define SL_DBAT7        0x90
  35 #define SL_IBAT7        0x98
  36 #define SL_TB           0xa0
  37 #define SL_R2           0xa8
  38 #define SL_CR           0xac
  39 #define SL_LR           0xb0
  40 #define SL_R12          0xb4    /* r12 to r31 */
  41 #define SL_SIZE         (SL_R12 + 80)
  42 
  43         .section .data
  44         .align  5
  45 
  46 _GLOBAL(swsusp_save_area)
  47         .space  SL_SIZE
  48 
  49 
  50         .section .text
  51         .align  5
  52 
  53 _GLOBAL(swsusp_arch_suspend)
  54 
  55         lis     r11,swsusp_save_area@h
  56         ori     r11,r11,swsusp_save_area@l
  57 
  58         mflr    r0
  59         stw     r0,SL_LR(r11)
  60         mfcr    r0
  61         stw     r0,SL_CR(r11)
  62         stw     r1,SL_SP(r11)
  63         stw     r2,SL_R2(r11)
  64         stmw    r12,SL_R12(r11)
  65 
  66         /* Save MSR & SDR1 */
  67         mfmsr   r4
  68         stw     r4,SL_MSR(r11)
  69         mfsdr1  r4
  70         stw     r4,SL_SDR1(r11)
  71 
  72         /* Get a stable timebase and save it */
  73 1:      mftbu   r4
  74         stw     r4,SL_TB(r11)
  75         mftb    r5
  76         stw     r5,SL_TB+4(r11)
  77         mftbu   r3
  78         cmpw    r3,r4
  79         bne     1b
  80 
  81         /* Save SPRGs */
  82         mfsprg  r4,0
  83         stw     r4,SL_SPRG0(r11)
  84         mfsprg  r4,1
  85         stw     r4,SL_SPRG0+4(r11)
  86         mfsprg  r4,2
  87         stw     r4,SL_SPRG0+8(r11)
  88         mfsprg  r4,3
  89         stw     r4,SL_SPRG0+12(r11)
  90 
  91         /* Save BATs */
  92         mfdbatu r4,0
  93         stw     r4,SL_DBAT0(r11)
  94         mfdbatl r4,0
  95         stw     r4,SL_DBAT0+4(r11)
  96         mfdbatu r4,1
  97         stw     r4,SL_DBAT1(r11)
  98         mfdbatl r4,1
  99         stw     r4,SL_DBAT1+4(r11)
 100         mfdbatu r4,2
 101         stw     r4,SL_DBAT2(r11)
 102         mfdbatl r4,2
 103         stw     r4,SL_DBAT2+4(r11)
 104         mfdbatu r4,3
 105         stw     r4,SL_DBAT3(r11)
 106         mfdbatl r4,3
 107         stw     r4,SL_DBAT3+4(r11)
 108         mfibatu r4,0
 109         stw     r4,SL_IBAT0(r11)
 110         mfibatl r4,0
 111         stw     r4,SL_IBAT0+4(r11)
 112         mfibatu r4,1
 113         stw     r4,SL_IBAT1(r11)
 114         mfibatl r4,1
 115         stw     r4,SL_IBAT1+4(r11)
 116         mfibatu r4,2
 117         stw     r4,SL_IBAT2(r11)
 118         mfibatl r4,2
 119         stw     r4,SL_IBAT2+4(r11)
 120         mfibatu r4,3
 121         stw     r4,SL_IBAT3(r11)
 122         mfibatl r4,3
 123         stw     r4,SL_IBAT3+4(r11)
 124 
 125 BEGIN_MMU_FTR_SECTION
 126         mfspr   r4,SPRN_DBAT4U
 127         stw     r4,SL_DBAT4(r11)
 128         mfspr   r4,SPRN_DBAT4L
 129         stw     r4,SL_DBAT4+4(r11)
 130         mfspr   r4,SPRN_DBAT5U
 131         stw     r4,SL_DBAT5(r11)
 132         mfspr   r4,SPRN_DBAT5L
 133         stw     r4,SL_DBAT5+4(r11)
 134         mfspr   r4,SPRN_DBAT6U
 135         stw     r4,SL_DBAT6(r11)
 136         mfspr   r4,SPRN_DBAT6L
 137         stw     r4,SL_DBAT6+4(r11)
 138         mfspr   r4,SPRN_DBAT7U
 139         stw     r4,SL_DBAT7(r11)
 140         mfspr   r4,SPRN_DBAT7L
 141         stw     r4,SL_DBAT7+4(r11)
 142         mfspr   r4,SPRN_IBAT4U
 143         stw     r4,SL_IBAT4(r11)
 144         mfspr   r4,SPRN_IBAT4L
 145         stw     r4,SL_IBAT4+4(r11)
 146         mfspr   r4,SPRN_IBAT5U
 147         stw     r4,SL_IBAT5(r11)
 148         mfspr   r4,SPRN_IBAT5L
 149         stw     r4,SL_IBAT5+4(r11)
 150         mfspr   r4,SPRN_IBAT6U
 151         stw     r4,SL_IBAT6(r11)
 152         mfspr   r4,SPRN_IBAT6L
 153         stw     r4,SL_IBAT6+4(r11)
 154         mfspr   r4,SPRN_IBAT7U
 155         stw     r4,SL_IBAT7(r11)
 156         mfspr   r4,SPRN_IBAT7L
 157         stw     r4,SL_IBAT7+4(r11)
 158 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 159 
 160 #if  0
 161         /* Backup various CPU config stuffs */
 162         bl      __save_cpu_setup
 163 #endif
 164         /* Call the low level suspend stuff (we should probably have made
 165          * a stackframe...
 166          */
 167         bl      swsusp_save
 168 
 169         /* Restore LR from the save area */
 170         lis     r11,swsusp_save_area@h
 171         ori     r11,r11,swsusp_save_area@l
 172         lwz     r0,SL_LR(r11)
 173         mtlr    r0
 174 
 175         blr
 176 
 177 
 178 /* Resume code */
 179 _GLOBAL(swsusp_arch_resume)
 180 
 181 #ifdef CONFIG_ALTIVEC
 182         /* Stop pending alitvec streams and memory accesses */
 183 BEGIN_FTR_SECTION
 184         DSSALL
 185 END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 186 #endif
 187         sync
 188 
 189         /* Disable MSR:DR to make sure we don't take a TLB or
 190          * hash miss during the copy, as our hash table will
 191          * for a while be unusable. For .text, we assume we are
 192          * covered by a BAT. This works only for non-G5 at this
 193          * point. G5 will need a better approach, possibly using
 194          * a small temporary hash table filled with large mappings,
 195          * disabling the MMU completely isn't a good option for
 196          * performance reasons.
 197          * (Note that 750's may have the same performance issue as
 198          * the G5 in this case, we should investigate using moving
 199          * BATs for these CPUs)
 200          */
 201         mfmsr   r0
 202         sync
 203         rlwinm  r0,r0,0,28,26           /* clear MSR_DR */
 204         mtmsr   r0
 205         sync
 206         isync
 207 
 208         /* Load ptr the list of pages to copy in r3 */
 209         lis     r11,(restore_pblist - KERNELBASE)@h
 210         ori     r11,r11,restore_pblist@l
 211         lwz     r10,0(r11)
 212 
 213         /* Copy the pages. This is a very basic implementation, to
 214          * be replaced by something more cache efficient */
 215 1:
 216         tophys(r3,r10)
 217         li      r0,256
 218         mtctr   r0
 219         lwz     r11,pbe_address(r3)     /* source */
 220         tophys(r5,r11)
 221         lwz     r10,pbe_orig_address(r3)        /* destination */
 222         tophys(r6,r10)
 223 2:
 224         lwz     r8,0(r5)
 225         lwz     r9,4(r5)
 226         lwz     r10,8(r5)
 227         lwz     r11,12(r5)
 228         addi    r5,r5,16
 229         stw     r8,0(r6)
 230         stw     r9,4(r6)
 231         stw     r10,8(r6)
 232         stw     r11,12(r6)
 233         addi    r6,r6,16
 234         bdnz    2b
 235         lwz             r10,pbe_next(r3)
 236         cmpwi   0,r10,0
 237         bne     1b
 238 
 239         /* Do a very simple cache flush/inval of the L1 to ensure
 240          * coherency of the icache
 241          */
 242         lis     r3,0x0002
 243         mtctr   r3
 244         li      r3, 0
 245 1:
 246         lwz     r0,0(r3)
 247         addi    r3,r3,0x0020
 248         bdnz    1b
 249         isync
 250         sync
 251 
 252         /* Now flush those cache lines */
 253         lis     r3,0x0002
 254         mtctr   r3
 255         li      r3, 0
 256 1:
 257         dcbf    0,r3
 258         addi    r3,r3,0x0020
 259         bdnz    1b
 260         sync
 261 
 262         /* Ok, we are now running with the kernel data of the old
 263          * kernel fully restored. We can get to the save area
 264          * easily now. As for the rest of the code, it assumes the
 265          * loader kernel and the booted one are exactly identical
 266          */
 267         lis     r11,swsusp_save_area@h
 268         ori     r11,r11,swsusp_save_area@l
 269         tophys(r11,r11)
 270 
 271 #if 0
 272         /* Restore various CPU config stuffs */
 273         bl      __restore_cpu_setup
 274 #endif
 275         /* Restore the BATs, and SDR1.  Then we can turn on the MMU.
 276          * This is a bit hairy as we are running out of those BATs,
 277          * but first, our code is probably in the icache, and we are
 278          * writing the same value to the BAT, so that should be fine,
 279          * though a better solution will have to be found long-term
 280          */
 281         lwz     r4,SL_SDR1(r11)
 282         mtsdr1  r4
 283         lwz     r4,SL_SPRG0(r11)
 284         mtsprg  0,r4
 285         lwz     r4,SL_SPRG0+4(r11)
 286         mtsprg  1,r4
 287         lwz     r4,SL_SPRG0+8(r11)
 288         mtsprg  2,r4
 289         lwz     r4,SL_SPRG0+12(r11)
 290         mtsprg  3,r4
 291 
 292 #if 0
 293         lwz     r4,SL_DBAT0(r11)
 294         mtdbatu 0,r4
 295         lwz     r4,SL_DBAT0+4(r11)
 296         mtdbatl 0,r4
 297         lwz     r4,SL_DBAT1(r11)
 298         mtdbatu 1,r4
 299         lwz     r4,SL_DBAT1+4(r11)
 300         mtdbatl 1,r4
 301         lwz     r4,SL_DBAT2(r11)
 302         mtdbatu 2,r4
 303         lwz     r4,SL_DBAT2+4(r11)
 304         mtdbatl 2,r4
 305         lwz     r4,SL_DBAT3(r11)
 306         mtdbatu 3,r4
 307         lwz     r4,SL_DBAT3+4(r11)
 308         mtdbatl 3,r4
 309         lwz     r4,SL_IBAT0(r11)
 310         mtibatu 0,r4
 311         lwz     r4,SL_IBAT0+4(r11)
 312         mtibatl 0,r4
 313         lwz     r4,SL_IBAT1(r11)
 314         mtibatu 1,r4
 315         lwz     r4,SL_IBAT1+4(r11)
 316         mtibatl 1,r4
 317         lwz     r4,SL_IBAT2(r11)
 318         mtibatu 2,r4
 319         lwz     r4,SL_IBAT2+4(r11)
 320         mtibatl 2,r4
 321         lwz     r4,SL_IBAT3(r11)
 322         mtibatu 3,r4
 323         lwz     r4,SL_IBAT3+4(r11)
 324         mtibatl 3,r4
 325 BEGIN_MMU_FTR_SECTION
 326         lwz     r4,SL_DBAT4(r11)
 327         mtspr   SPRN_DBAT4U,r4
 328         lwz     r4,SL_DBAT4+4(r11)
 329         mtspr   SPRN_DBAT4L,r4
 330         lwz     r4,SL_DBAT5(r11)
 331         mtspr   SPRN_DBAT5U,r4
 332         lwz     r4,SL_DBAT5+4(r11)
 333         mtspr   SPRN_DBAT5L,r4
 334         lwz     r4,SL_DBAT6(r11)
 335         mtspr   SPRN_DBAT6U,r4
 336         lwz     r4,SL_DBAT6+4(r11)
 337         mtspr   SPRN_DBAT6L,r4
 338         lwz     r4,SL_DBAT7(r11)
 339         mtspr   SPRN_DBAT7U,r4
 340         lwz     r4,SL_DBAT7+4(r11)
 341         mtspr   SPRN_DBAT7L,r4
 342         lwz     r4,SL_IBAT4(r11)
 343         mtspr   SPRN_IBAT4U,r4
 344         lwz     r4,SL_IBAT4+4(r11)
 345         mtspr   SPRN_IBAT4L,r4
 346         lwz     r4,SL_IBAT5(r11)
 347         mtspr   SPRN_IBAT5U,r4
 348         lwz     r4,SL_IBAT5+4(r11)
 349         mtspr   SPRN_IBAT5L,r4
 350         lwz     r4,SL_IBAT6(r11)
 351         mtspr   SPRN_IBAT6U,r4
 352         lwz     r4,SL_IBAT6+4(r11)
 353         mtspr   SPRN_IBAT6L,r4
 354         lwz     r4,SL_IBAT7(r11)
 355         mtspr   SPRN_IBAT7U,r4
 356         lwz     r4,SL_IBAT7+4(r11)
 357         mtspr   SPRN_IBAT7L,r4
 358 END_MMU_FTR_SECTION_IFSET(MMU_FTR_USE_HIGH_BATS)
 359 #endif
 360 
 361         /* Flush all TLBs */
 362         lis     r4,0x1000
 363 1:      addic.  r4,r4,-0x1000
 364         tlbie   r4
 365         bgt     1b
 366         sync
 367 
 368         /* restore the MSR and turn on the MMU */
 369         lwz     r3,SL_MSR(r11)
 370         bl      turn_on_mmu
 371         tovirt(r11,r11)
 372 
 373         /* Restore TB */
 374         li      r3,0
 375         mttbl   r3
 376         lwz     r3,SL_TB(r11)
 377         lwz     r4,SL_TB+4(r11)
 378         mttbu   r3
 379         mttbl   r4
 380 
 381         /* Kick decrementer */
 382         li      r0,1
 383         mtdec   r0
 384 
 385         /* Restore the callee-saved registers and return */
 386         lwz     r0,SL_CR(r11)
 387         mtcr    r0
 388         lwz     r2,SL_R2(r11)
 389         lmw     r12,SL_R12(r11)
 390         lwz     r1,SL_SP(r11)
 391         lwz     r0,SL_LR(r11)
 392         mtlr    r0
 393 
 394         // XXX Note: we don't really need to call swsusp_resume
 395 
 396         li      r3,0
 397         blr
 398 
 399 /* FIXME:This construct is actually not useful since we don't shut
 400  * down the instruction MMU, we could just flip back MSR-DR on.
 401  */
 402 turn_on_mmu:
 403         mflr    r4
 404         mtsrr0  r4
 405         mtsrr1  r3
 406         sync
 407         isync
 408         rfi
 409 

/* [<][>][^][v][top][bottom][index][help] */