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