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