root/arch/ia64/kernel/pal.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  21 pal_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  */
  33 GLOBAL_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
  39 END(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  */
  46 GLOBAL_ENTRY(ia64_pal_default_handler)
  47         mov r8=-1
  48         br.cond.sptk.many rp
  49 END(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  */
  57 GLOBAL_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
  61 1:      {
  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
  84 1:      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                          // seralize restoration of psr.l
  90         br.ret.sptk.many b0
  91 END(ia64_pal_call_static)
  92 EXPORT_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  */
 101 GLOBAL_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
 127 END(ia64_pal_call_stacked)
 128 EXPORT_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 
 149 GLOBAL_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
 153 1:      {
 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
 185 1:
 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                          // seralize restoration of psr.l
 198         br.ret.sptk.many b0
 199 END(ia64_pal_call_phys_static)
 200 EXPORT_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  */
 209 GLOBAL_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
 213 1:      {
 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                          // seralize restoration of psr.l
 256         br.ret.sptk.many b0
 257 END(ia64_pal_call_phys_stacked)
 258 EXPORT_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  */
 270 GLOBAL_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
 283 END(ia64_save_scratch_fpregs)
 284 EXPORT_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  */
 292 GLOBAL_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
 305 END(ia64_load_scratch_fpregs)
 306 EXPORT_SYMBOL(ia64_load_scratch_fpregs)

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