root/arch/parisc/kernel/real2.S

/* [<][>][^][v][top][bottom][index][help] */
   1 /*
   2  *
   3  * This file is subject to the terms and conditions of the GNU General Public
   4  * License.  See the file "COPYING" in the main directory of this archive
   5  * for more details.
   6  *
   7  * Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
   8  *
   9  */
  10 
  11 #include <asm/pdc.h>
  12 #include <asm/psw.h>
  13 #include <asm/assembly.h>
  14 #include <asm/asm-offsets.h>
  15 
  16 #include <linux/linkage.h>
  17 
  18 
  19         .section        .bss
  20 
  21         .export pdc_result
  22         .export pdc_result2
  23         .align 8
  24 pdc_result:
  25         .block  ASM_PDC_RESULT_SIZE
  26 pdc_result2:
  27         .block  ASM_PDC_RESULT_SIZE
  28 
  29         .export real_stack
  30         .export real32_stack
  31         .export real64_stack
  32         .align  64
  33 real_stack:
  34 real32_stack:
  35 real64_stack:
  36         .block  8192
  37 
  38 #define N_SAVED_REGS 9
  39 
  40 save_cr_space:
  41         .block  REG_SZ * N_SAVED_REGS
  42 save_cr_end:
  43 
  44 
  45 /************************ 32-bit real-mode calls ***********************/
  46 /* This can be called in both narrow and wide kernels */
  47 
  48         .text
  49 
  50         /* unsigned long real32_call_asm(unsigned int *sp,
  51          *              unsigned int *arg0p,
  52          *              unsigned int iodc_fn)
  53          *      sp is value of stack pointer to adopt before calling PDC (virt)
  54          *      arg0p points to where saved arg values may be found
  55          *      iodc_fn is the IODC function to call
  56          */
  57 
  58 ENTRY_CFI(real32_call_asm)
  59         STREG   %rp, -RP_OFFSET(%sp)    /* save RP */
  60 #ifdef CONFIG_64BIT
  61         callee_save
  62         ldo     2*REG_SZ(%sp), %sp      /* room for a couple more saves */
  63         STREG   %r27, -1*REG_SZ(%sp)
  64         STREG   %r29, -2*REG_SZ(%sp)
  65 #endif
  66         STREG   %sp, -REG_SZ(%arg0)     /* save SP on real-mode stack */
  67         copy    %arg0, %sp              /* adopt the real-mode SP */
  68 
  69         /* save iodc_fn */
  70         copy    %arg2, %r31
  71 
  72         /* load up the arg registers from the saved arg area */
  73         /* 32-bit calling convention passes first 4 args in registers */
  74         ldw     0(%arg1), %arg0         /* note overwriting arg0 */
  75         ldw     -8(%arg1), %arg2
  76         ldw     -12(%arg1), %arg3
  77         ldw     -4(%arg1), %arg1        /* obviously must do this one last! */
  78 
  79         tophys_r1  %sp
  80 
  81         b,l     rfi_virt2real,%r2
  82         nop
  83 
  84         b,l     save_control_regs,%r2           /* modifies r1, r2, r28 */
  85         nop
  86 
  87 #ifdef CONFIG_64BIT
  88         rsm     PSW_SM_W, %r0           /* go narrow */
  89 #endif
  90 
  91         load32  PA(ric_ret), %r2
  92         bv      0(%r31)
  93         nop
  94 ric_ret:
  95 #ifdef CONFIG_64BIT
  96         ssm     PSW_SM_W, %r0           /* go wide */
  97 #endif
  98         /* restore CRs before going virtual in case we page fault */
  99         b,l     restore_control_regs, %r2       /* modifies r1, r2, r26 */
 100         nop
 101 
 102         b,l     rfi_real2virt,%r2
 103         nop
 104 
 105         tovirt_r1 %sp
 106         LDREG   -REG_SZ(%sp), %sp       /* restore SP */
 107 #ifdef CONFIG_64BIT
 108         LDREG   -1*REG_SZ(%sp), %r27
 109         LDREG   -2*REG_SZ(%sp), %r29
 110         ldo     -2*REG_SZ(%sp), %sp
 111         callee_rest
 112 #endif
 113         LDREG   -RP_OFFSET(%sp), %rp    /* restore RP */
 114         bv      0(%rp)
 115         nop
 116 ENDPROC_CFI(real32_call_asm)
 117 
 118 
 119 #  define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where)
 120 #  define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r
 121 
 122         .text
 123 ENTRY_CFI(save_control_regs)
 124         load32  PA(save_cr_space), %r28
 125         PUSH_CR(%cr24, %r28)
 126         PUSH_CR(%cr25, %r28)
 127         PUSH_CR(%cr26, %r28)
 128         PUSH_CR(%cr27, %r28)
 129         PUSH_CR(%cr28, %r28)
 130         PUSH_CR(%cr29, %r28)
 131         PUSH_CR(%cr30, %r28)
 132         PUSH_CR(%cr31, %r28)
 133         PUSH_CR(%cr15, %r28)
 134         bv 0(%r2)
 135         nop
 136 ENDPROC_CFI(save_control_regs)
 137 
 138 ENTRY_CFI(restore_control_regs)
 139         load32  PA(save_cr_end), %r26
 140         POP_CR(%cr15, %r26)
 141         POP_CR(%cr31, %r26)
 142         POP_CR(%cr30, %r26)
 143         POP_CR(%cr29, %r26)
 144         POP_CR(%cr28, %r26)
 145         POP_CR(%cr27, %r26)
 146         POP_CR(%cr26, %r26)
 147         POP_CR(%cr25, %r26)
 148         POP_CR(%cr24, %r26)
 149         bv 0(%r2)
 150         nop
 151 ENDPROC_CFI(restore_control_regs)
 152 
 153 /* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for
 154  * more general-purpose use by the several places which need RFIs
 155  */
 156         .text
 157         .align 128
 158 ENTRY_CFI(rfi_virt2real)
 159 #if !defined(BOOTLOADER)
 160         /* switch to real mode... */
 161         rsm             PSW_SM_I,%r0
 162         load32          PA(rfi_v2r_1), %r1
 163         nop
 164         nop
 165         nop
 166         nop
 167         nop
 168         
 169         rsm             PSW_SM_Q,%r0  /* disable Q & I bits to load iia queue */
 170         mtctl           %r0, %cr17      /* Clear IIASQ tail */
 171         mtctl           %r0, %cr17      /* Clear IIASQ head */
 172         mtctl           %r1, %cr18      /* IIAOQ head */
 173         ldo             4(%r1), %r1
 174         mtctl           %r1, %cr18      /* IIAOQ tail */
 175         load32          REAL_MODE_PSW, %r1
 176         mtctl           %r1, %cr22
 177         rfi
 178         
 179         nop
 180         nop
 181         nop
 182         nop
 183         nop
 184         nop
 185         nop
 186         nop
 187 rfi_v2r_1:
 188         tophys_r1 %r2
 189 #endif /* defined(BOOTLOADER) */
 190         bv      0(%r2)
 191         nop
 192 ENDPROC_CFI(rfi_virt2real)
 193 
 194         .text
 195         .align 128
 196 ENTRY_CFI(rfi_real2virt)
 197 #if !defined(BOOTLOADER)
 198         rsm             PSW_SM_I,%r0
 199         load32          (rfi_r2v_1), %r1
 200         nop
 201         nop
 202         nop
 203         nop
 204         nop
 205         
 206         rsm             PSW_SM_Q,%r0    /* disable Q bit to load iia queue */
 207         mtctl           %r0, %cr17      /* Clear IIASQ tail */
 208         mtctl           %r0, %cr17      /* Clear IIASQ head */
 209         mtctl           %r1, %cr18      /* IIAOQ head */
 210         ldo             4(%r1), %r1
 211         mtctl           %r1, %cr18      /* IIAOQ tail */
 212         load32          KERNEL_PSW, %r1
 213         mtctl           %r1, %cr22
 214         rfi
 215         
 216         nop
 217         nop
 218         nop
 219         nop
 220         nop
 221         nop
 222         nop
 223         nop
 224 rfi_r2v_1:
 225         tovirt_r1 %r2
 226 #endif /* defined(BOOTLOADER) */
 227         bv      0(%r2)
 228         nop
 229 ENDPROC_CFI(rfi_real2virt)
 230 
 231 #ifdef CONFIG_64BIT
 232 
 233 /************************ 64-bit real-mode calls ***********************/
 234 /* This is only usable in wide kernels right now and will probably stay so */
 235         .text
 236         /* unsigned long real64_call_asm(unsigned long *sp,
 237          *              unsigned long *arg0p,
 238          *              unsigned long fn)
 239          *      sp is value of stack pointer to adopt before calling PDC (virt)
 240          *      arg0p points to where saved arg values may be found
 241          *      iodc_fn is the IODC function to call
 242          */
 243 ENTRY_CFI(real64_call_asm)
 244         std     %rp, -0x10(%sp)         /* save RP */
 245         std     %sp, -8(%arg0)          /* save SP on real-mode stack */
 246         copy    %arg0, %sp              /* adopt the real-mode SP */
 247 
 248         /* save fn */
 249         copy    %arg2, %r31
 250 
 251         /* set up the new ap */
 252         ldo     64(%arg1), %r29
 253 
 254         /* load up the arg registers from the saved arg area */
 255         /* 32-bit calling convention passes first 4 args in registers */
 256         ldd     0*REG_SZ(%arg1), %arg0          /* note overwriting arg0 */
 257         ldd     2*REG_SZ(%arg1), %arg2
 258         ldd     3*REG_SZ(%arg1), %arg3
 259         ldd     4*REG_SZ(%arg1), %r22
 260         ldd     5*REG_SZ(%arg1), %r21
 261         ldd     6*REG_SZ(%arg1), %r20
 262         ldd     7*REG_SZ(%arg1), %r19
 263         ldd     1*REG_SZ(%arg1), %arg1          /* do this one last! */
 264 
 265         tophys_r1 %sp
 266 
 267         b,l     rfi_virt2real,%r2
 268         nop
 269 
 270         b,l     save_control_regs,%r2           /* modifies r1, r2, r28 */
 271         nop
 272 
 273         load32  PA(r64_ret), %r2
 274         bv      0(%r31)
 275         nop
 276 r64_ret:
 277         /* restore CRs before going virtual in case we page fault */
 278         b,l     restore_control_regs, %r2       /* modifies r1, r2, r26 */
 279         nop
 280 
 281         b,l     rfi_real2virt,%r2
 282         nop
 283 
 284         tovirt_r1 %sp
 285         ldd     -8(%sp), %sp            /* restore SP */
 286         ldd     -0x10(%sp), %rp         /* restore RP */
 287         bv      0(%rp)
 288         nop
 289 ENDPROC_CFI(real64_call_asm)
 290 
 291 #endif
 292 
 293         .text
 294         /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html
 295         **      GCC 3.3 and later has a new function in libgcc.a for
 296         **      comparing function pointers.
 297         */
 298 ENTRY_CFI(__canonicalize_funcptr_for_compare)
 299 #ifdef CONFIG_64BIT
 300         bve (%r2)
 301 #else
 302         bv %r0(%r2)
 303 #endif
 304         copy %r26,%r28
 305 ENDPROC_CFI(__canonicalize_funcptr_for_compare)
 306 

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