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) 106 HMT_MEDIUM 107 108 mfcr r0 109 stw r0,8(r1) 110 HCALL_BRANCH(plpar_hcall_norets_trace) 111 HVSC /* invoke the hypervisor */ 112 113 lwz r0,8(r1) 114 mtcrf 0xff,r0 115 blr /* return r3 = status */ 116 117#ifdef CONFIG_TRACEPOINTS 118plpar_hcall_norets_trace: 119 HCALL_INST_PRECALL(R4) 120 HVSC 121 HCALL_INST_POSTCALL_NORETS 122 lwz r0,8(r1) 123 mtcrf 0xff,r0 124 blr 125#endif 126 127_GLOBAL_TOC(plpar_hcall) 128 HMT_MEDIUM 129 130 mfcr r0 131 stw r0,8(r1) 132 133 HCALL_BRANCH(plpar_hcall_trace) 134 135 std r4,STK_PARAM(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_PARAM(R4)(r1) 147 std r4, 0(r12) 148 std r5, 8(r12) 149 std r6, 16(r12) 150 std r7, 24(r12) 151 152 lwz r0,8(r1) 153 mtcrf 0xff,r0 154 155 blr /* return r3 = status */ 156 157#ifdef CONFIG_TRACEPOINTS 158plpar_hcall_trace: 159 HCALL_INST_PRECALL(R5) 160 161 std r4,STK_PARAM(R4)(r1) 162 mr r0,r4 163 164 mr r4,r5 165 mr r5,r6 166 mr r6,r7 167 mr r7,r8 168 mr r8,r9 169 mr r9,r10 170 171 HVSC 172 173 ld r12,STK_PARAM(R4)(r1) 174 std r4,0(r12) 175 std r5,8(r12) 176 std r6,16(r12) 177 std r7,24(r12) 178 179 HCALL_INST_POSTCALL(r12) 180 181 lwz r0,8(r1) 182 mtcrf 0xff,r0 183 184 blr 185#endif 186 187/* 188 * plpar_hcall_raw can be called in real mode. kexec/kdump need some 189 * hypervisor calls to be executed in real mode. So plpar_hcall_raw 190 * does not access the per cpu hypervisor call statistics variables, 191 * since these variables may not be present in the RMO region. 192 */ 193_GLOBAL(plpar_hcall_raw) 194 HMT_MEDIUM 195 196 mfcr r0 197 stw r0,8(r1) 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 208 HVSC /* invoke the hypervisor */ 209 210 ld r12,STK_PARAM(R4)(r1) 211 std r4, 0(r12) 212 std r5, 8(r12) 213 std r6, 16(r12) 214 std r7, 24(r12) 215 216 lwz r0,8(r1) 217 mtcrf 0xff,r0 218 219 blr /* return r3 = status */ 220 221_GLOBAL_TOC(plpar_hcall9) 222 HMT_MEDIUM 223 224 mfcr r0 225 stw r0,8(r1) 226 227 HCALL_BRANCH(plpar_hcall9_trace) 228 229 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 230 231 mr r4,r5 232 mr r5,r6 233 mr r6,r7 234 mr r7,r8 235 mr r8,r9 236 mr r9,r10 237 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ 238 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ 239 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ 240 241 HVSC /* invoke the hypervisor */ 242 243 mr r0,r12 244 ld r12,STK_PARAM(R4)(r1) 245 std r4, 0(r12) 246 std r5, 8(r12) 247 std r6, 16(r12) 248 std r7, 24(r12) 249 std r8, 32(r12) 250 std r9, 40(r12) 251 std r10,48(r12) 252 std r11,56(r12) 253 std r0, 64(r12) 254 255 lwz r0,8(r1) 256 mtcrf 0xff,r0 257 258 blr /* return r3 = status */ 259 260#ifdef CONFIG_TRACEPOINTS 261plpar_hcall9_trace: 262 HCALL_INST_PRECALL(R5) 263 264 std r4,STK_PARAM(R4)(r1) 265 mr r0,r4 266 267 mr r4,r5 268 mr r5,r6 269 mr r6,r7 270 mr r7,r8 271 mr r8,r9 272 mr r9,r10 273 ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1) 274 ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1) 275 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1) 276 277 HVSC 278 279 mr r0,r12 280 ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1) 281 std r4,0(r12) 282 std r5,8(r12) 283 std r6,16(r12) 284 std r7,24(r12) 285 std r8,32(r12) 286 std r9,40(r12) 287 std r10,48(r12) 288 std r11,56(r12) 289 std r0,64(r12) 290 291 HCALL_INST_POSTCALL(r12) 292 293 lwz r0,8(r1) 294 mtcrf 0xff,r0 295 296 blr 297#endif 298 299/* See plpar_hcall_raw to see why this is needed */ 300_GLOBAL(plpar_hcall9_raw) 301 HMT_MEDIUM 302 303 mfcr r0 304 stw r0,8(r1) 305 306 std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ 307 308 mr r4,r5 309 mr r5,r6 310 mr r6,r7 311 mr r7,r8 312 mr r8,r9 313 mr r9,r10 314 ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */ 315 ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */ 316 ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */ 317 318 HVSC /* invoke the hypervisor */ 319 320 mr r0,r12 321 ld r12,STK_PARAM(R4)(r1) 322 std r4, 0(r12) 323 std r5, 8(r12) 324 std r6, 16(r12) 325 std r7, 24(r12) 326 std r8, 32(r12) 327 std r9, 40(r12) 328 std r10,48(r12) 329 std r11,56(r12) 330 std r0, 64(r12) 331 332 lwz r0,8(r1) 333 mtcrf 0xff,r0 334 335 blr /* return r3 = status */ 336