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#include <asm/jump_label.h> 16 17 .section ".text" 18 19#ifdef CONFIG_TRACEPOINTS 20 21#ifndef HAVE_JUMP_LABEL 22 .section ".toc","aw" 23 24 .globl hcall_tracepoint_refcount 25hcall_tracepoint_refcount: 26 .llong 0 27 28 .section ".text" 29#endif 30 31/* 32 * precall must preserve all registers. use unused STK_PARAM() 33 * areas to save snapshots and opcode. 34 */ 35#define HCALL_INST_PRECALL(FIRST_REG) \ 36 mflr r0; \ 37 std r3,STK_PARAM(R3)(r1); \ 38 std r4,STK_PARAM(R4)(r1); \ 39 std r5,STK_PARAM(R5)(r1); \ 40 std r6,STK_PARAM(R6)(r1); \ 41 std r7,STK_PARAM(R7)(r1); \ 42 std r8,STK_PARAM(R8)(r1); \ 43 std r9,STK_PARAM(R9)(r1); \ 44 std r10,STK_PARAM(R10)(r1); \ 45 std r0,16(r1); \ 46 addi r4,r1,STK_PARAM(FIRST_REG); \ 47 stdu r1,-STACK_FRAME_OVERHEAD(r1); \ 48 bl __trace_hcall_entry; \ 49 ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ 50 ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \ 51 ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \ 52 ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \ 53 ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \ 54 ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \ 55 ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \ 56 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1) 57 58/* 59 * postcall is performed immediately before function return which 60 * allows liberal use of volatile registers. 61 */ 62#define __HCALL_INST_POSTCALL \ 63 ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ 64 std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ 65 mr r4,r3; \ 66 mr r3,r0; \ 67 bl __trace_hcall_exit; \ 68 ld r0,STACK_FRAME_OVERHEAD+16(r1); \ 69 addi r1,r1,STACK_FRAME_OVERHEAD; \ 70 ld r3,STK_PARAM(R3)(r1); \ 71 mtlr r0 72 73#define HCALL_INST_POSTCALL_NORETS \ 74 li r5,0; \ 75 __HCALL_INST_POSTCALL 76 77#define HCALL_INST_POSTCALL(BUFREG) \ 78 mr r5,BUFREG; \ 79 __HCALL_INST_POSTCALL 80 81#ifdef HAVE_JUMP_LABEL 82#define HCALL_BRANCH(LABEL) \ 83 ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key) 84#else 85 86/* 87 * We branch around this in early init (eg when populating the MMU 88 * hashtable) by using an unconditional cpu feature. 89 */ 90#define HCALL_BRANCH(LABEL) \ 91BEGIN_FTR_SECTION; \ 92 b 1f; \ 93END_FTR_SECTION(0, 1); \ 94 ld r12,hcall_tracepoint_refcount@toc(r2); \ 95 std r12,32(r1); \ 96 cmpdi r12,0; \ 97 bne- LABEL; \ 981: 99#endif 100 101#else 102#define HCALL_INST_PRECALL(FIRST_ARG) 103#define HCALL_INST_POSTCALL_NORETS 104#define HCALL_INST_POSTCALL(BUFREG) 105#define HCALL_BRANCH(LABEL) 106#endif 107 108_GLOBAL_TOC(plpar_hcall_norets) 109 HMT_MEDIUM 110 111 mfcr r0 112 stw r0,8(r1) 113 HCALL_BRANCH(plpar_hcall_norets_trace) 114 HVSC /* invoke the hypervisor */ 115 116 lwz r0,8(r1) 117 mtcrf 0xff,r0 118 blr /* return r3 = status */ 119 120#ifdef CONFIG_TRACEPOINTS 121plpar_hcall_norets_trace: 122 HCALL_INST_PRECALL(R4) 123 HVSC 124 HCALL_INST_POSTCALL_NORETS 125 lwz r0,8(r1) 126 mtcrf 0xff,r0 127 blr 128#endif 129 130_GLOBAL_TOC(plpar_hcall) 131 HMT_MEDIUM 132 133 mfcr r0 134 stw r0,8(r1) 135 136 HCALL_BRANCH(plpar_hcall_trace) 137 138 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 139 140 mr r4,r5 141 mr r5,r6 142 mr r6,r7 143 mr r7,r8 144 mr r8,r9 145 mr r9,r10 146 147 HVSC /* invoke the hypervisor */ 148 149 ld r12,STK_PARAM(R4)(r1) 150 std r4, 0(r12) 151 std r5, 8(r12) 152 std r6, 16(r12) 153 std r7, 24(r12) 154 155 lwz r0,8(r1) 156 mtcrf 0xff,r0 157 158 blr /* return r3 = status */ 159 160#ifdef CONFIG_TRACEPOINTS 161plpar_hcall_trace: 162 HCALL_INST_PRECALL(R5) 163 164 std r4,STK_PARAM(R4)(r1) 165 mr r0,r4 166 167 mr r4,r5 168 mr r5,r6 169 mr r6,r7 170 mr r7,r8 171 mr r8,r9 172 mr r9,r10 173 174 HVSC 175 176 ld r12,STK_PARAM(R4)(r1) 177 std r4,0(r12) 178 std r5,8(r12) 179 std r6,16(r12) 180 std r7,24(r12) 181 182 HCALL_INST_POSTCALL(r12) 183 184 lwz r0,8(r1) 185 mtcrf 0xff,r0 186 187 blr 188#endif 189 190/* 191 * plpar_hcall_raw can be called in real mode. kexec/kdump need some 192 * hypervisor calls to be executed in real mode. So plpar_hcall_raw 193 * does not access the per cpu hypervisor call statistics variables, 194 * since these variables may not be present in the RMO region. 195 */ 196_GLOBAL(plpar_hcall_raw) 197 HMT_MEDIUM 198 199 mfcr r0 200 stw r0,8(r1) 201 202 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 203 204 mr r4,r5 205 mr r5,r6 206 mr r6,r7 207 mr r7,r8 208 mr r8,r9 209 mr r9,r10 210 211 HVSC /* invoke the hypervisor */ 212 213 ld r12,STK_PARAM(R4)(r1) 214 std r4, 0(r12) 215 std r5, 8(r12) 216 std r6, 16(r12) 217 std r7, 24(r12) 218 219 lwz r0,8(r1) 220 mtcrf 0xff,r0 221 222 blr /* return r3 = status */ 223 224_GLOBAL_TOC(plpar_hcall9) 225 HMT_MEDIUM 226 227 mfcr r0 228 stw r0,8(r1) 229 230 HCALL_BRANCH(plpar_hcall9_trace) 231 232 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 233 234 mr r4,r5 235 mr r5,r6 236 mr r6,r7 237 mr r7,r8 238 mr r8,r9 239 mr r9,r10 240 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ 241 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ 242 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ 243 244 HVSC /* invoke the hypervisor */ 245 246 mr r0,r12 247 ld r12,STK_PARAM(R4)(r1) 248 std r4, 0(r12) 249 std r5, 8(r12) 250 std r6, 16(r12) 251 std r7, 24(r12) 252 std r8, 32(r12) 253 std r9, 40(r12) 254 std r10,48(r12) 255 std r11,56(r12) 256 std r0, 64(r12) 257 258 lwz r0,8(r1) 259 mtcrf 0xff,r0 260 261 blr /* return r3 = status */ 262 263#ifdef CONFIG_TRACEPOINTS 264plpar_hcall9_trace: 265 HCALL_INST_PRECALL(R5) 266 267 std r4,STK_PARAM(R4)(r1) 268 mr r0,r4 269 270 mr r4,r5 271 mr r5,r6 272 mr r6,r7 273 mr r7,r8 274 mr r8,r9 275 mr r9,r10 276 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1) 277 ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1) 278 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1) 279 280 HVSC 281 282 mr r0,r12 283 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1) 284 std r4,0(r12) 285 std r5,8(r12) 286 std r6,16(r12) 287 std r7,24(r12) 288 std r8,32(r12) 289 std r9,40(r12) 290 std r10,48(r12) 291 std r11,56(r12) 292 std r0,64(r12) 293 294 HCALL_INST_POSTCALL(r12) 295 296 lwz r0,8(r1) 297 mtcrf 0xff,r0 298 299 blr 300#endif 301 302/* See plpar_hcall_raw to see why this is needed */ 303_GLOBAL(plpar_hcall9_raw) 304 HMT_MEDIUM 305 306 mfcr r0 307 stw r0,8(r1) 308 309 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 310 311 mr r4,r5 312 mr r5,r6 313 mr r6,r7 314 mr r7,r8 315 mr r8,r9 316 mr r9,r10 317 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ 318 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ 319 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ 320 321 HVSC /* invoke the hypervisor */ 322 323 mr r0,r12 324 ld r12,STK_PARAM(R4)(r1) 325 std r4, 0(r12) 326 std r5, 8(r12) 327 std r6, 16(r12) 328 std r7, 24(r12) 329 std r8, 32(r12) 330 std r9, 40(r12) 331 std r10,48(r12) 332 std r11,56(r12) 333 std r0, 64(r12) 334 335 lwz r0,8(r1) 336 mtcrf 0xff,r0 337 338 blr /* return r3 = status */ 339