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