1/* 2 * This file contains the generic code to perform a call to the 3 * pSeries LPAR hypervisor. 4 * 5 * This program is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU General Public License 7 * as published by the Free Software Foundation; either version 8 * 2 of the License, or (at your option) any later version. 9 */ 10#include <asm/hvcall.h> 11#include <asm/processor.h> 12#include <asm/ppc_asm.h> 13#include <asm/asm-offsets.h> 14#include <asm/ptrace.h> 15 16#define STK_PARM(i) (48 + ((i)-3)*8) 17 18#ifdef CONFIG_TRACEPOINTS 19 20 .section ".toc","aw" 21 22 .globl hcall_tracepoint_refcount 23hcall_tracepoint_refcount: 24 .llong 0 25 26 .section ".text" 27 28/* 29 * precall must preserve all registers. use unused STK_PARM() 30 * areas to save snapshots and opcode. We branch around this 31 * in early init (eg when populating the MMU hashtable) by using an 32 * unconditional cpu feature. 33 */ 34#define HCALL_INST_PRECALL(FIRST_REG) \ 35BEGIN_FTR_SECTION; \ 36 b 1f; \ 37END_FTR_SECTION(0, 1); \ 38 ld r12,hcall_tracepoint_refcount@toc(r2); \ 39 std r12,32(r1); \ 40 cmpdi r12,0; \ 41 beq+ 1f; \ 42 mflr r0; \ 43 std r3,STK_PARM(r3)(r1); \ 44 std r4,STK_PARM(r4)(r1); \ 45 std r5,STK_PARM(r5)(r1); \ 46 std r6,STK_PARM(r6)(r1); \ 47 std r7,STK_PARM(r7)(r1); \ 48 std r8,STK_PARM(r8)(r1); \ 49 std r9,STK_PARM(r9)(r1); \ 50 std r10,STK_PARM(r10)(r1); \ 51 std r0,16(r1); \ 52 addi r4,r1,STK_PARM(FIRST_REG); \ 53 stdu r1,-STACK_FRAME_OVERHEAD(r1); \ 54 bl .__trace_hcall_entry; \ 55 addi r1,r1,STACK_FRAME_OVERHEAD; \ 56 ld r0,16(r1); \ 57 ld r3,STK_PARM(r3)(r1); \ 58 ld r4,STK_PARM(r4)(r1); \ 59 ld r5,STK_PARM(r5)(r1); \ 60 ld r6,STK_PARM(r6)(r1); \ 61 ld r7,STK_PARM(r7)(r1); \ 62 ld r8,STK_PARM(r8)(r1); \ 63 ld r9,STK_PARM(r9)(r1); \ 64 ld r10,STK_PARM(r10)(r1); \ 65 mtlr r0; \ 661: 67 68/* 69 * postcall is performed immediately before function return which 70 * allows liberal use of volatile registers. We branch around this 71 * in early init (eg when populating the MMU hashtable) by using an 72 * unconditional cpu feature. 73 */ 74#define __HCALL_INST_POSTCALL \ 75BEGIN_FTR_SECTION; \ 76 b 1f; \ 77END_FTR_SECTION(0, 1); \ 78 ld r12,32(r1); \ 79 cmpdi r12,0; \ 80 beq+ 1f; \ 81 mflr r0; \ 82 ld r6,STK_PARM(r3)(r1); \ 83 std r3,STK_PARM(r3)(r1); \ 84 mr r4,r3; \ 85 mr r3,r6; \ 86 std r0,16(r1); \ 87 stdu r1,-STACK_FRAME_OVERHEAD(r1); \ 88 bl .__trace_hcall_exit; \ 89 addi r1,r1,STACK_FRAME_OVERHEAD; \ 90 ld r0,16(r1); \ 91 ld r3,STK_PARM(r3)(r1); \ 92 mtlr r0; \ 931: 94 95#define HCALL_INST_POSTCALL_NORETS \ 96 li r5,0; \ 97 __HCALL_INST_POSTCALL 98 99#define HCALL_INST_POSTCALL(BUFREG) \ 100 mr r5,BUFREG; \ 101 __HCALL_INST_POSTCALL 102 103#else 104#define HCALL_INST_PRECALL(FIRST_ARG) 105#define HCALL_INST_POSTCALL_NORETS 106#define HCALL_INST_POSTCALL(BUFREG) 107#endif 108 109 .text 110 111_GLOBAL(plpar_hcall_norets) 112 HMT_MEDIUM 113 114 mfcr r0 115 stw r0,8(r1) 116 117 HCALL_INST_PRECALL(r4) 118 119 HVSC /* invoke the hypervisor */ 120 121 HCALL_INST_POSTCALL_NORETS 122 123 lwz r0,8(r1) 124 mtcrf 0xff,r0 125 blr /* return r3 = status */ 126 127_GLOBAL(plpar_hcall) 128 HMT_MEDIUM 129 130 mfcr r0 131 stw r0,8(r1) 132 133 HCALL_INST_PRECALL(r5) 134 135 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 136 137 mr r4,r5 138 mr r5,r6 139 mr r6,r7 140 mr r7,r8 141 mr r8,r9 142 mr r9,r10 143 144 HVSC /* invoke the hypervisor */ 145 146 ld r12,STK_PARM(r4)(r1) 147 std r4, 0(r12) 148 std r5, 8(r12) 149 std r6, 16(r12) 150 std r7, 24(r12) 151 152 HCALL_INST_POSTCALL(r12) 153 154 lwz r0,8(r1) 155 mtcrf 0xff,r0 156 157 blr /* return r3 = status */ 158 159/* 160 * plpar_hcall_raw can be called in real mode. kexec/kdump need some 161 * hypervisor calls to be executed in real mode. So plpar_hcall_raw 162 * does not access the per cpu hypervisor call statistics variables, 163 * since these variables may not be present in the RMO region. 164 */ 165_GLOBAL(plpar_hcall_raw) 166 HMT_MEDIUM 167 168 mfcr r0 169 stw r0,8(r1) 170 171 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 172 173 mr r4,r5 174 mr r5,r6 175 mr r6,r7 176 mr r7,r8 177 mr r8,r9 178 mr r9,r10 179 180 HVSC /* invoke the hypervisor */ 181 182 ld r12,STK_PARM(r4)(r1) 183 std r4, 0(r12) 184 std r5, 8(r12) 185 std r6, 16(r12) 186 std r7, 24(r12) 187 188 lwz r0,8(r1) 189 mtcrf 0xff,r0 190 191 blr /* return r3 = status */ 192 193_GLOBAL(plpar_hcall9) 194 HMT_MEDIUM 195 196 mfcr r0 197 stw r0,8(r1) 198 199 HCALL_INST_PRECALL(r5) 200 201 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 202 203 mr r4,r5 204 mr r5,r6 205 mr r6,r7 206 mr r7,r8 207 mr r8,r9 208 mr r9,r10 209 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ 210 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ 211 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ 212 213 HVSC /* invoke the hypervisor */ 214 215 mr r0,r12 216 ld r12,STK_PARM(r4)(r1) 217 std r4, 0(r12) 218 std r5, 8(r12) 219 std r6, 16(r12) 220 std r7, 24(r12) 221 std r8, 32(r12) 222 std r9, 40(r12) 223 std r10,48(r12) 224 std r11,56(r12) 225 std r0, 64(r12) 226 227 HCALL_INST_POSTCALL(r12) 228 229 lwz r0,8(r1) 230 mtcrf 0xff,r0 231 232 blr /* return r3 = status */ 233 234/* See plpar_hcall_raw to see why this is needed */ 235_GLOBAL(plpar_hcall9_raw) 236 HMT_MEDIUM 237 238 mfcr r0 239 stw r0,8(r1) 240 241 std r4,STK_PARM(r4)(r1) /* Save ret buffer */ 242 243 mr r4,r5 244 mr r5,r6 245 mr r6,r7 246 mr r7,r8 247 mr r8,r9 248 mr r9,r10 249 ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */ 250 ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */ 251 ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */ 252 253 HVSC /* invoke the hypervisor */ 254 255 mr r0,r12 256 ld r12,STK_PARM(r4)(r1) 257 std r4, 0(r12) 258 std r5, 8(r12) 259 std r6, 16(r12) 260 std r7, 24(r12) 261 std r8, 32(r12) 262 std r9, 40(r12) 263 std r10,48(r12) 264 std r11,56(r12) 265 std r0, 64(r12) 266 267 lwz r0,8(r1) 268 mtcrf 0xff,r0 269 270 blr /* return r3 = status */ 271