Path: blob/master/arch/powerpc/platforms/pseries/hvCall.S
26481 views
/* SPDX-License-Identifier: GPL-2.0-or-later */1/*2* This file contains the generic code to perform a call to the3* pSeries LPAR hypervisor.4*/5#include <linux/jump_label.h>6#include <asm/hvcall.h>7#include <asm/processor.h>8#include <asm/ppc_asm.h>9#include <asm/asm-offsets.h>10#include <asm/ptrace.h>11#include <asm/feature-fixups.h>1213.section ".text"1415#ifdef CONFIG_TRACEPOINTS1617#ifndef CONFIG_JUMP_LABEL18.data1920.globl hcall_tracepoint_refcount21hcall_tracepoint_refcount:22.8byte 02324.section ".text"25#endif2627/*28* precall must preserve all registers. use unused STK_PARAM()29* areas to save snapshots and opcode. STK_PARAM() in the caller's30* frame will be available even on ELFv2 because these are all31* variadic functions.32*/33#define HCALL_INST_PRECALL(FIRST_REG) \34mflr r0; \35std r3,STK_PARAM(R3)(r1); \36std r4,STK_PARAM(R4)(r1); \37std r5,STK_PARAM(R5)(r1); \38std r6,STK_PARAM(R6)(r1); \39std r7,STK_PARAM(R7)(r1); \40std r8,STK_PARAM(R8)(r1); \41std r9,STK_PARAM(R9)(r1); \42std r10,STK_PARAM(R10)(r1); \43std r0,16(r1); \44addi r4,r1,STK_PARAM(FIRST_REG); \45stdu r1,-STACK_FRAME_MIN_SIZE(r1); \46bl CFUNC(__trace_hcall_entry); \47ld r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1); \48ld r4,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1); \49ld r5,STACK_FRAME_MIN_SIZE+STK_PARAM(R5)(r1); \50ld r6,STACK_FRAME_MIN_SIZE+STK_PARAM(R6)(r1); \51ld r7,STACK_FRAME_MIN_SIZE+STK_PARAM(R7)(r1); \52ld r8,STACK_FRAME_MIN_SIZE+STK_PARAM(R8)(r1); \53ld r9,STACK_FRAME_MIN_SIZE+STK_PARAM(R9)(r1); \54ld r10,STACK_FRAME_MIN_SIZE+STK_PARAM(R10)(r1)5556/*57* postcall is performed immediately before function return which58* allows liberal use of volatile registers.59*/60#define __HCALL_INST_POSTCALL \61ld r0,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1); \62std r3,STACK_FRAME_MIN_SIZE+STK_PARAM(R3)(r1); \63mr r4,r3; \64mr r3,r0; \65bl CFUNC(__trace_hcall_exit); \66ld r0,STACK_FRAME_MIN_SIZE+16(r1); \67addi r1,r1,STACK_FRAME_MIN_SIZE; \68ld r3,STK_PARAM(R3)(r1); \69mtlr r07071#define HCALL_INST_POSTCALL_NORETS \72li r5,0; \73__HCALL_INST_POSTCALL7475#define HCALL_INST_POSTCALL(BUFREG) \76mr r5,BUFREG; \77__HCALL_INST_POSTCALL7879#ifdef CONFIG_JUMP_LABEL80#define HCALL_BRANCH(LABEL) \81ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)82#else8384/*85* We branch around this in early init (eg when populating the MMU86* hashtable) by using an unconditional cpu feature.87*/88#define HCALL_BRANCH(LABEL) \89BEGIN_FTR_SECTION; \90b 1f; \91END_FTR_SECTION(0, 1); \92LOAD_REG_ADDR(r12, hcall_tracepoint_refcount) ; \93ld r12,0(r12); \94cmpdi r12,0; \95bne- LABEL; \961:97#endif9899#else100#define HCALL_INST_PRECALL(FIRST_ARG)101#define HCALL_INST_POSTCALL_NORETS102#define HCALL_INST_POSTCALL(BUFREG)103#define HCALL_BRANCH(LABEL)104#endif105106_GLOBAL_TOC(plpar_hcall_norets_notrace)107HMT_MEDIUM108109mfcr r0110stw r0,8(r1)111HVSC /* invoke the hypervisor */112113li r4,0114stb r4,PACASRR_VALID(r13)115116lwz r0,8(r1)117mtcrf 0xff,r0118blr /* return r3 = status */119120_GLOBAL_TOC(plpar_hcall_norets)121HMT_MEDIUM122123mfcr r0124stw r0,8(r1)125HCALL_BRANCH(plpar_hcall_norets_trace)126HVSC /* invoke the hypervisor */127128li r4,0129stb r4,PACASRR_VALID(r13)130131lwz r0,8(r1)132mtcrf 0xff,r0133blr /* return r3 = status */134135#ifdef CONFIG_TRACEPOINTS136plpar_hcall_norets_trace:137HCALL_INST_PRECALL(R4)138HVSC139HCALL_INST_POSTCALL_NORETS140141li r4,0142stb r4,PACASRR_VALID(r13)143144lwz r0,8(r1)145mtcrf 0xff,r0146blr147#endif148149_GLOBAL_TOC(plpar_hcall)150HMT_MEDIUM151152mfcr r0153stw r0,8(r1)154155HCALL_BRANCH(plpar_hcall_trace)156157std r4,STK_PARAM(R4)(r1) /* Save ret buffer */158159mr r4,r5160mr r5,r6161mr r6,r7162mr r7,r8163mr r8,r9164mr r9,r10165166HVSC /* invoke the hypervisor */167168ld r12,STK_PARAM(R4)(r1)169std r4, 0(r12)170std r5, 8(r12)171std r6, 16(r12)172std r7, 24(r12)173174li r4,0175stb r4,PACASRR_VALID(r13)176177lwz r0,8(r1)178mtcrf 0xff,r0179180blr /* return r3 = status */181182#ifdef CONFIG_TRACEPOINTS183plpar_hcall_trace:184HCALL_INST_PRECALL(R5)185186mr r4,r5187mr r5,r6188mr r6,r7189mr r7,r8190mr r8,r9191mr r9,r10192193HVSC194195ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1)196std r4,0(r12)197std r5,8(r12)198std r6,16(r12)199std r7,24(r12)200201HCALL_INST_POSTCALL(r12)202203li r4,0204stb r4,PACASRR_VALID(r13)205206lwz r0,8(r1)207mtcrf 0xff,r0208209blr210#endif211212/*213* plpar_hcall_raw can be called in real mode. kexec/kdump need some214* hypervisor calls to be executed in real mode. So plpar_hcall_raw215* does not access the per cpu hypervisor call statistics variables,216* since these variables may not be present in the RMO region.217*/218_GLOBAL(plpar_hcall_raw)219HMT_MEDIUM220221mfcr r0222stw r0,8(r1)223224std r4,STK_PARAM(R4)(r1) /* Save ret buffer */225226mr r4,r5227mr r5,r6228mr r6,r7229mr r7,r8230mr r8,r9231mr r9,r10232233HVSC /* invoke the hypervisor */234235ld r12,STK_PARAM(R4)(r1)236std r4, 0(r12)237std r5, 8(r12)238std r6, 16(r12)239std r7, 24(r12)240241li r4,0242stb r4,PACASRR_VALID(r13)243244lwz r0,8(r1)245mtcrf 0xff,r0246247blr /* return r3 = status */248249_GLOBAL_TOC(plpar_hcall9)250HMT_MEDIUM251252mfcr r0253stw r0,8(r1)254255HCALL_BRANCH(plpar_hcall9_trace)256257std r4,STK_PARAM(R4)(r1) /* Save ret buffer */258259mr r4,r5260mr r5,r6261mr r6,r7262mr r7,r8263mr r8,r9264mr r9,r10265ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */266ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */267ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */268269HVSC /* invoke the hypervisor */270271mr r0,r12272ld r12,STK_PARAM(R4)(r1)273std r4, 0(r12)274std r5, 8(r12)275std r6, 16(r12)276std r7, 24(r12)277std r8, 32(r12)278std r9, 40(r12)279std r10,48(r12)280std r11,56(r12)281std r0, 64(r12)282283li r4,0284stb r4,PACASRR_VALID(r13)285286lwz r0,8(r1)287mtcrf 0xff,r0288289blr /* return r3 = status */290291#ifdef CONFIG_TRACEPOINTS292plpar_hcall9_trace:293HCALL_INST_PRECALL(R5)294295mr r4,r5296mr r5,r6297mr r6,r7298mr r7,r8299mr r8,r9300mr r9,r10301ld r10,STACK_FRAME_MIN_SIZE+STK_PARAM(R11)(r1)302ld r11,STACK_FRAME_MIN_SIZE+STK_PARAM(R12)(r1)303ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R13)(r1)304305HVSC306307mr r0,r12308ld r12,STACK_FRAME_MIN_SIZE+STK_PARAM(R4)(r1)309std r4,0(r12)310std r5,8(r12)311std r6,16(r12)312std r7,24(r12)313std r8,32(r12)314std r9,40(r12)315std r10,48(r12)316std r11,56(r12)317std r0,64(r12)318319HCALL_INST_POSTCALL(r12)320321li r4,0322stb r4,PACASRR_VALID(r13)323324lwz r0,8(r1)325mtcrf 0xff,r0326327blr328#endif329330/* See plpar_hcall_raw to see why this is needed */331_GLOBAL(plpar_hcall9_raw)332HMT_MEDIUM333334mfcr r0335stw r0,8(r1)336337std r4,STK_PARAM(R4)(r1) /* Save ret buffer */338339mr r4,r5340mr r5,r6341mr r6,r7342mr r7,r8343mr r8,r9344mr r9,r10345ld r10,STK_PARAM(R11)(r1) /* put arg7 in R10 */346ld r11,STK_PARAM(R12)(r1) /* put arg8 in R11 */347ld r12,STK_PARAM(R13)(r1) /* put arg9 in R12 */348349HVSC /* invoke the hypervisor */350351mr r0,r12352ld r12,STK_PARAM(R4)(r1)353std r4, 0(r12)354std r5, 8(r12)355std r6, 16(r12)356std r7, 24(r12)357std r8, 32(r12)358std r9, 40(r12)359std r10,48(r12)360std r11,56(r12)361std r0, 64(r12)362363li r4,0364stb r4,PACASRR_VALID(r13)365366lwz r0,8(r1)367mtcrf 0xff,r0368369blr /* return r3 = status */370371372