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