Path: blob/master/arch/powerpc/platforms/pseries/hvCall.S
10818 views
/*1* This file contains the generic code to perform a call to the2* pSeries LPAR hypervisor.3*4* This program is free software; you can redistribute it and/or5* modify it under the terms of the GNU General Public License6* as published by the Free Software Foundation; either version7* 2 of the License, or (at your option) any later version.8*/9#include <asm/hvcall.h>10#include <asm/processor.h>11#include <asm/ppc_asm.h>12#include <asm/asm-offsets.h>13#include <asm/ptrace.h>1415#define STK_PARM(i) (48 + ((i)-3)*8)1617#ifdef CONFIG_TRACEPOINTS1819.section ".toc","aw"2021.globl hcall_tracepoint_refcount22hcall_tracepoint_refcount:23.llong 02425.section ".text"2627/*28* precall must preserve all registers. use unused STK_PARM()29* areas to save snapshots and opcode. We branch around this30* in early init (eg when populating the MMU hashtable) by using an31* unconditional cpu feature.32*/33#define HCALL_INST_PRECALL(FIRST_REG) \34BEGIN_FTR_SECTION; \35b 1f; \36END_FTR_SECTION(0, 1); \37ld r12,hcall_tracepoint_refcount@toc(r2); \38cmpdi r12,0; \39beq+ 1f; \40mflr r0; \41std r3,STK_PARM(r3)(r1); \42std r4,STK_PARM(r4)(r1); \43std r5,STK_PARM(r5)(r1); \44std r6,STK_PARM(r6)(r1); \45std r7,STK_PARM(r7)(r1); \46std r8,STK_PARM(r8)(r1); \47std r9,STK_PARM(r9)(r1); \48std r10,STK_PARM(r10)(r1); \49std r0,16(r1); \50addi r4,r1,STK_PARM(FIRST_REG); \51stdu r1,-STACK_FRAME_OVERHEAD(r1); \52bl .__trace_hcall_entry; \53addi r1,r1,STACK_FRAME_OVERHEAD; \54ld r0,16(r1); \55ld r3,STK_PARM(r3)(r1); \56ld r4,STK_PARM(r4)(r1); \57ld r5,STK_PARM(r5)(r1); \58ld r6,STK_PARM(r6)(r1); \59ld r7,STK_PARM(r7)(r1); \60ld r8,STK_PARM(r8)(r1); \61ld r9,STK_PARM(r9)(r1); \62ld r10,STK_PARM(r10)(r1); \63mtlr r0; \641:6566/*67* postcall is performed immediately before function return which68* allows liberal use of volatile registers. We branch around this69* in early init (eg when populating the MMU hashtable) by using an70* unconditional cpu feature.71*/72#define __HCALL_INST_POSTCALL \73BEGIN_FTR_SECTION; \74b 1f; \75END_FTR_SECTION(0, 1); \76ld r12,hcall_tracepoint_refcount@toc(r2); \77cmpdi r12,0; \78beq+ 1f; \79mflr r0; \80ld r6,STK_PARM(r3)(r1); \81std r3,STK_PARM(r3)(r1); \82mr r4,r3; \83mr r3,r6; \84std r0,16(r1); \85stdu r1,-STACK_FRAME_OVERHEAD(r1); \86bl .__trace_hcall_exit; \87addi r1,r1,STACK_FRAME_OVERHEAD; \88ld r0,16(r1); \89ld r3,STK_PARM(r3)(r1); \90mtlr r0; \911:9293#define HCALL_INST_POSTCALL_NORETS \94li r5,0; \95__HCALL_INST_POSTCALL9697#define HCALL_INST_POSTCALL(BUFREG) \98mr r5,BUFREG; \99__HCALL_INST_POSTCALL100101#else102#define HCALL_INST_PRECALL(FIRST_ARG)103#define HCALL_INST_POSTCALL_NORETS104#define HCALL_INST_POSTCALL(BUFREG)105#endif106107.text108109_GLOBAL(plpar_hcall_norets)110HMT_MEDIUM111112mfcr r0113stw r0,8(r1)114115HCALL_INST_PRECALL(r4)116117HVSC /* invoke the hypervisor */118119HCALL_INST_POSTCALL_NORETS120121lwz r0,8(r1)122mtcrf 0xff,r0123blr /* return r3 = status */124125_GLOBAL(plpar_hcall)126HMT_MEDIUM127128mfcr r0129stw r0,8(r1)130131HCALL_INST_PRECALL(r5)132133std r4,STK_PARM(r4)(r1) /* Save ret buffer */134135mr r4,r5136mr r5,r6137mr r6,r7138mr r7,r8139mr r8,r9140mr r9,r10141142HVSC /* invoke the hypervisor */143144ld r12,STK_PARM(r4)(r1)145std r4, 0(r12)146std r5, 8(r12)147std r6, 16(r12)148std r7, 24(r12)149150HCALL_INST_POSTCALL(r12)151152lwz r0,8(r1)153mtcrf 0xff,r0154155blr /* return r3 = status */156157/*158* plpar_hcall_raw can be called in real mode. kexec/kdump need some159* hypervisor calls to be executed in real mode. So plpar_hcall_raw160* 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)164HMT_MEDIUM165166mfcr r0167stw r0,8(r1)168169std r4,STK_PARM(r4)(r1) /* Save ret buffer */170171mr r4,r5172mr r5,r6173mr r6,r7174mr r7,r8175mr r8,r9176mr r9,r10177178HVSC /* invoke the hypervisor */179180ld r12,STK_PARM(r4)(r1)181std r4, 0(r12)182std r5, 8(r12)183std r6, 16(r12)184std r7, 24(r12)185186lwz r0,8(r1)187mtcrf 0xff,r0188189blr /* return r3 = status */190191_GLOBAL(plpar_hcall9)192HMT_MEDIUM193194mfcr r0195stw r0,8(r1)196197HCALL_INST_PRECALL(r5)198199std r4,STK_PARM(r4)(r1) /* Save ret buffer */200201mr r4,r5202mr r5,r6203mr r6,r7204mr r7,r8205mr r8,r9206mr r9,r10207ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */208ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */209ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */210211HVSC /* invoke the hypervisor */212213mr r0,r12214ld r12,STK_PARM(r4)(r1)215std r4, 0(r12)216std r5, 8(r12)217std r6, 16(r12)218std r7, 24(r12)219std r8, 32(r12)220std r9, 40(r12)221std r10,48(r12)222std r11,56(r12)223std r0, 64(r12)224225HCALL_INST_POSTCALL(r12)226227lwz r0,8(r1)228mtcrf 0xff,r0229230blr /* return r3 = status */231232/* See plpar_hcall_raw to see why this is needed */233_GLOBAL(plpar_hcall9_raw)234HMT_MEDIUM235236mfcr r0237stw r0,8(r1)238239std r4,STK_PARM(r4)(r1) /* Save ret buffer */240241mr r4,r5242mr r5,r6243mr r6,r7244mr r7,r8245mr r8,r9246mr r9,r10247ld r10,STK_PARM(r11)(r1) /* put arg7 in R10 */248ld r11,STK_PARM(r12)(r1) /* put arg8 in R11 */249ld r12,STK_PARM(r13)(r1) /* put arg9 in R12 */250251HVSC /* invoke the hypervisor */252253mr r0,r12254ld r12,STK_PARM(r4)(r1)255std r4, 0(r12)256std r5, 8(r12)257std r6, 16(r12)258std r7, 24(r12)259std r8, 32(r12)260std r9, 40(r12)261std r10,48(r12)262std r11,56(r12)263std r0, 64(r12)264265lwz r0,8(r1)266mtcrf 0xff,r0267268blr /* return r3 = status */269270271