root/arch/powerpc/platforms/pseries/hvCall.S

/* [<][>][^][v][top][bottom][index][help] */
   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
  22 hcall_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)                                     \
  88 BEGIN_FTR_SECTION;                                              \
  89         b       1f;                                             \
  90 END_FTR_SECTION(0, 1);                                          \
  91         ld      r12,hcall_tracepoint_refcount@toc(r2);          \
  92         std     r12,32(r1);                                     \
  93         cmpdi   r12,0;                                          \
  94         bne-    LABEL;                                          \
  95 1:
  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
 118 plpar_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
 158 plpar_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
 261 plpar_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 */

/* [<][>][^][v][top][bottom][index][help] */