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