linux/arch/ia64/kernel/pal.S
<<
>>
Prefs
   1/*
   2 * PAL Firmware support
   3 * IA-64 Processor Programmers Reference Vol 2
   4 *
   5 * Copyright (C) 1999 Don Dugger <don.dugger@intel.com>
   6 * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
   7 * Copyright (C) 1999-2001, 2003 Hewlett-Packard Co
   8 *      David Mosberger <davidm@hpl.hp.com>
   9 *      Stephane Eranian <eranian@hpl.hp.com>
  10 *
  11 * 05/22/2000 eranian Added support for stacked register calls
  12 * 05/24/2000 eranian Added support for physical mode static calls
  13 */
  14
  15#include <asm/asmmacro.h>
  16#include <asm/processor.h>
  17#include <asm/export.h>
  18
  19        .data
  20pal_entry_point:
  21        data8 ia64_pal_default_handler
  22        .text
  23
  24/*
  25 * Set the PAL entry point address.  This could be written in C code, but we
  26 * do it here to keep it all in one module (besides, it's so trivial that it's
  27 * not a big deal).
  28 *
  29 * in0          Address of the PAL entry point (text address, NOT a function
  30 *              descriptor).
  31 */
  32GLOBAL_ENTRY(ia64_pal_handler_init)
  33        alloc r3=ar.pfs,1,0,0,0
  34        movl r2=pal_entry_point
  35        ;;
  36        st8 [r2]=in0
  37        br.ret.sptk.many rp
  38END(ia64_pal_handler_init)
  39
  40/*
  41 * Default PAL call handler.  This needs to be coded in assembly because it
  42 * uses the static calling convention, i.e., the RSE may not be used and
  43 * calls are done via "br.cond" (not "br.call").
  44 */
  45GLOBAL_ENTRY(ia64_pal_default_handler)
  46        mov r8=-1
  47        br.cond.sptk.many rp
  48END(ia64_pal_default_handler)
  49
  50/*
  51 * Make a PAL call using the static calling convention.
  52 *
  53 * in0         Index of PAL service
  54 * in1 - in3   Remaining PAL arguments
  55 */
  56GLOBAL_ENTRY(ia64_pal_call_static)
  57        .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
  58        alloc loc1 = ar.pfs,4,5,0,0
  59        movl loc2 = pal_entry_point
  601:      {
  61          mov r28 = in0
  62          mov r29 = in1
  63          mov r8 = ip
  64        }
  65        ;;
  66        ld8 loc2 = [loc2]               // loc2 <- entry point
  67        adds r8 = 1f-1b,r8
  68        mov loc4=ar.rsc                 // save RSE configuration
  69        ;;
  70        mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
  71        mov loc3 = psr
  72        mov loc0 = rp
  73        .body
  74        mov r30 = in2
  75
  76        mov r31 = in3
  77        mov b7 = loc2
  78
  79        rsm psr.i
  80        ;;
  81        mov rp = r8
  82        br.cond.sptk.many b7
  831:      mov psr.l = loc3
  84        mov ar.rsc = loc4               // restore RSE configuration
  85        mov ar.pfs = loc1
  86        mov rp = loc0
  87        ;;
  88        srlz.d                          // seralize restoration of psr.l
  89        br.ret.sptk.many b0
  90END(ia64_pal_call_static)
  91EXPORT_SYMBOL(ia64_pal_call_static)
  92
  93/*
  94 * Make a PAL call using the stacked registers calling convention.
  95 *
  96 * Inputs:
  97 *      in0         Index of PAL service
  98 *      in2 - in3   Remaining PAL arguments
  99 */
 100GLOBAL_ENTRY(ia64_pal_call_stacked)
 101        .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
 102        alloc loc1 = ar.pfs,4,4,4,0
 103        movl loc2 = pal_entry_point
 104
 105        mov r28  = in0                  // Index MUST be copied to r28
 106        mov out0 = in0                  // AND in0 of PAL function
 107        mov loc0 = rp
 108        .body
 109        ;;
 110        ld8 loc2 = [loc2]               // loc2 <- entry point
 111        mov out1 = in1
 112        mov out2 = in2
 113        mov out3 = in3
 114        mov loc3 = psr
 115        ;;
 116        rsm psr.i
 117        mov b7 = loc2
 118        ;;
 119        br.call.sptk.many rp=b7         // now make the call
 120.ret0:  mov psr.l  = loc3
 121        mov ar.pfs = loc1
 122        mov rp = loc0
 123        ;;
 124        srlz.d                          // serialize restoration of psr.l
 125        br.ret.sptk.many b0
 126END(ia64_pal_call_stacked)
 127EXPORT_SYMBOL(ia64_pal_call_stacked)
 128
 129/*
 130 * Make a physical mode PAL call using the static registers calling convention.
 131 *
 132 * Inputs:
 133 *      in0         Index of PAL service
 134 *      in2 - in3   Remaining PAL arguments
 135 *
 136 * PSR_LP, PSR_TB, PSR_ID, PSR_DA are never set by the kernel.
 137 * So we don't need to clear them.
 138 */
 139#define PAL_PSR_BITS_TO_CLEAR                                                 \
 140        (IA64_PSR_I | IA64_PSR_IT | IA64_PSR_DT  | IA64_PSR_DB | IA64_PSR_RT |\
 141         IA64_PSR_DD | IA64_PSR_SS | IA64_PSR_RI | IA64_PSR_ED |              \
 142         IA64_PSR_DFL | IA64_PSR_DFH)
 143
 144#define PAL_PSR_BITS_TO_SET                                                   \
 145        (IA64_PSR_BN)
 146
 147
 148GLOBAL_ENTRY(ia64_pal_call_phys_static)
 149        .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(4)
 150        alloc loc1 = ar.pfs,4,7,0,0
 151        movl loc2 = pal_entry_point
 1521:      {
 153          mov r28  = in0                // copy procedure index
 154          mov r8   = ip                 // save ip to compute branch
 155          mov loc0 = rp                 // save rp
 156        }
 157        .body
 158        ;;
 159        ld8 loc2 = [loc2]               // loc2 <- entry point
 160        mov r29  = in1                  // first argument
 161        mov r30  = in2                  // copy arg2
 162        mov r31  = in3                  // copy arg3
 163        ;;
 164        mov loc3 = psr                  // save psr
 165        adds r8  = 1f-1b,r8             // calculate return address for call
 166        ;;
 167        mov loc4=ar.rsc                 // save RSE configuration
 168        dep.z loc2=loc2,0,61            // convert pal entry point to physical
 169        tpa r8=r8                       // convert rp to physical
 170        ;;
 171        mov b7 = loc2                   // install target to branch reg
 172        mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
 173        movl r16=PAL_PSR_BITS_TO_CLEAR
 174        movl r17=PAL_PSR_BITS_TO_SET
 175        ;;
 176        or loc3=loc3,r17                // add in psr the bits to set
 177        ;;
 178        andcm r16=loc3,r16              // removes bits to clear from psr
 179        br.call.sptk.many rp=ia64_switch_mode_phys
 180        mov rp = r8                     // install return address (physical)
 181        mov loc5 = r19
 182        mov loc6 = r20
 183        br.cond.sptk.many b7
 1841:
 185        mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
 186        mov r16=loc3                    // r16= original psr
 187        mov r19=loc5
 188        mov r20=loc6
 189        br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
 190        mov psr.l = loc3                // restore init PSR
 191
 192        mov ar.pfs = loc1
 193        mov rp = loc0
 194        ;;
 195        mov ar.rsc=loc4                 // restore RSE configuration
 196        srlz.d                          // seralize restoration of psr.l
 197        br.ret.sptk.many b0
 198END(ia64_pal_call_phys_static)
 199EXPORT_SYMBOL(ia64_pal_call_phys_static)
 200
 201/*
 202 * Make a PAL call using the stacked registers in physical mode.
 203 *
 204 * Inputs:
 205 *      in0         Index of PAL service
 206 *      in2 - in3   Remaining PAL arguments
 207 */
 208GLOBAL_ENTRY(ia64_pal_call_phys_stacked)
 209        .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(5)
 210        alloc   loc1 = ar.pfs,5,7,4,0
 211        movl    loc2 = pal_entry_point
 2121:      {
 213          mov r28  = in0                // copy procedure index
 214          mov loc0 = rp                 // save rp
 215        }
 216        .body
 217        ;;
 218        ld8 loc2 = [loc2]               // loc2 <- entry point
 219        mov loc3 = psr                  // save psr
 220        ;;
 221        mov loc4=ar.rsc                 // save RSE configuration
 222        dep.z loc2=loc2,0,61            // convert pal entry point to physical
 223        ;;
 224        mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
 225        movl r16=PAL_PSR_BITS_TO_CLEAR
 226        movl r17=PAL_PSR_BITS_TO_SET
 227        ;;
 228        or loc3=loc3,r17                // add in psr the bits to set
 229        mov b7 = loc2                   // install target to branch reg
 230        ;;
 231        andcm r16=loc3,r16              // removes bits to clear from psr
 232        br.call.sptk.many rp=ia64_switch_mode_phys
 233
 234        mov out0 = in0                  // first argument
 235        mov out1 = in1                  // copy arg2
 236        mov out2 = in2                  // copy arg3
 237        mov out3 = in3                  // copy arg3
 238        mov loc5 = r19
 239        mov loc6 = r20
 240
 241        br.call.sptk.many rp=b7         // now make the call
 242
 243        mov ar.rsc=0                    // put RSE in enforced lazy, LE mode
 244        mov r16=loc3                    // r16= original psr
 245        mov r19=loc5
 246        mov r20=loc6
 247        br.call.sptk.many rp=ia64_switch_mode_virt // return to virtual mode
 248
 249        mov psr.l  = loc3               // restore init PSR
 250        mov ar.pfs = loc1
 251        mov rp = loc0
 252        ;;
 253        mov ar.rsc=loc4                 // restore RSE configuration
 254        srlz.d                          // seralize restoration of psr.l
 255        br.ret.sptk.many b0
 256END(ia64_pal_call_phys_stacked)
 257EXPORT_SYMBOL(ia64_pal_call_phys_stacked)
 258
 259/*
 260 * Save scratch fp scratch regs which aren't saved in pt_regs already
 261 * (fp10-fp15).
 262 *
 263 * NOTE: We need to do this since firmware (SAL and PAL) may use any of the
 264 * scratch regs fp-low partition.
 265 *
 266 * Inputs:
 267 *      in0     Address of stack storage for fp regs
 268 */
 269GLOBAL_ENTRY(ia64_save_scratch_fpregs)
 270        alloc r3=ar.pfs,1,0,0,0
 271        add r2=16,in0
 272        ;;
 273        stf.spill [in0] = f10,32
 274        stf.spill [r2]  = f11,32
 275        ;;
 276        stf.spill [in0] = f12,32
 277        stf.spill [r2]  = f13,32
 278        ;;
 279        stf.spill [in0] = f14,32
 280        stf.spill [r2]  = f15,32
 281        br.ret.sptk.many rp
 282END(ia64_save_scratch_fpregs)
 283EXPORT_SYMBOL(ia64_save_scratch_fpregs)
 284
 285/*
 286 * Load scratch fp scratch regs (fp10-fp15)
 287 *
 288 * Inputs:
 289 *      in0     Address of stack storage for fp regs
 290 */
 291GLOBAL_ENTRY(ia64_load_scratch_fpregs)
 292        alloc r3=ar.pfs,1,0,0,0
 293        add r2=16,in0
 294        ;;
 295        ldf.fill  f10 = [in0],32
 296        ldf.fill  f11 = [r2],32
 297        ;;
 298        ldf.fill  f12 = [in0],32
 299        ldf.fill  f13 = [r2],32
 300        ;;
 301        ldf.fill  f14 = [in0],32
 302        ldf.fill  f15 = [r2],32
 303        br.ret.sptk.many rp
 304END(ia64_load_scratch_fpregs)
 305EXPORT_SYMBOL(ia64_load_scratch_fpregs)
 306