From: Anton Blanchard Fix a number of bugs in our pseries hcall stubs: - store parameters in the area specified by the ABI, no need to create stack frames. - plpar_hcall_4out would corrupt r14 - merge multiple HVSC definitions Signed-off-by: Anton Blanchard Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc64/kernel/head.S | 2 25-akpm/arch/ppc64/kernel/pSeries_hvCall.S | 178 ++++++++++++----------------- 25-akpm/include/asm-ppc64/hvcall.h | 14 -- 3 files changed, 86 insertions(+), 108 deletions(-) diff -puN arch/ppc64/kernel/head.S~ppc64-fix-pseries-hcall-stubs arch/ppc64/kernel/head.S --- 25/arch/ppc64/kernel/head.S~ppc64-fix-pseries-hcall-stubs 2005-03-21 21:54:09.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/head.S 2005-03-21 21:54:09.000000000 -0800 @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -45,7 +46,6 @@ /* * hcall interface to pSeries LPAR */ -#define HVSC .long 0x44000022 #define H_SET_ASR 0x30 /* diff -puN arch/ppc64/kernel/pSeries_hvCall.S~ppc64-fix-pseries-hcall-stubs arch/ppc64/kernel/pSeries_hvCall.S --- 25/arch/ppc64/kernel/pSeries_hvCall.S~ppc64-fix-pseries-hcall-stubs 2005-03-21 21:54:09.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_hvCall.S 2005-03-21 21:54:09.000000000 -0800 @@ -1,7 +1,6 @@ /* * arch/ppc64/kernel/pSeries_hvCall.S * - * * This file contains the generic code to perform a call to the * pSeries LPAR hypervisor. * NOTE: this file will go away when we move to inline this work. @@ -11,133 +10,114 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ -#include -#include -#include +#include #include -#include -#include #include -/* - * hcall interface to pSeries LPAR - */ -#define HVSC .long 0x44000022 - -/* long plpar_hcall(unsigned long opcode, R3 - unsigned long arg1, R4 - unsigned long arg2, R5 - unsigned long arg3, R6 - unsigned long arg4, R7 - unsigned long *out1, R8 - unsigned long *out2, R9 - unsigned long *out3); R10 - */ +#define STK_PARM(i) (48 + ((i)-3)*8) .text + +/* long plpar_hcall(unsigned long opcode, R3 + unsigned long arg1, R4 + unsigned long arg2, R5 + unsigned long arg3, R6 + unsigned long arg4, R7 + unsigned long *out1, R8 + unsigned long *out2, R9 + unsigned long *out3); R10 + */ _GLOBAL(plpar_hcall) mfcr r0 - std r0,-8(r1) - stdu r1,-32(r1) - std r8,-8(r1) /* Save out ptrs. */ - std r9,-16(r1) - std r10,-24(r1) - - HVSC /* invoke the hypervisor */ + std r8,STK_PARM(r8)(r1) /* Save out ptrs */ + std r9,STK_PARM(r9)(r1) + std r10,STK_PARM(r10)(r1) + + stw r0,8(r1) + + HVSC /* invoke the hypervisor */ + + lwz r0,8(r1) + + ld r8,STK_PARM(r8)(r1) /* Fetch r4-r6 ret args */ + ld r9,STK_PARM(r9)(r1) + ld r10,STK_PARM(r10)(r1) + std r4,0(r8) + std r5,0(r9) + std r6,0(r10) - ld r10,-8(r1) /* Fetch r4-r7 ret args. */ - std r4,0(r10) - ld r10,-16(r1) - std r5,0(r10) - ld r10,-24(r1) - std r6,0(r10) - - ld r1,0(r1) - ld r0,-8(r1) mtcrf 0xff,r0 - blr /* return r3 = status */ + blr /* return r3 = status */ /* Simple interface with no output values (other than status) */ _GLOBAL(plpar_hcall_norets) mfcr r0 - std r0,-8(r1) - HVSC /* invoke the hypervisor */ - ld r0,-8(r1) - mtcrf 0xff,r0 - blr /* return r3 = status */ + stw r0,8(r1) + HVSC /* invoke the hypervisor */ -/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3 - unsigned long arg1, R4 - unsigned long arg2, R5 - unsigned long arg3, R6 - unsigned long arg4, R7 - unsigned long arg5, R8 - unsigned long arg6, R9 - unsigned long arg7, R10 - unsigned long arg8, 112(R1) - unsigned long *out1); 120(R1) + lwz r0,8(r1) + mtcrf 0xff,r0 + blr /* return r3 = status */ - */ - .text +/* long plpar_hcall_8arg_2ret(unsigned long opcode, R3 + unsigned long arg1, R4 + unsigned long arg2, R5 + unsigned long arg3, R6 + unsigned long arg4, R7 + unsigned long arg5, R8 + unsigned long arg6, R9 + unsigned long arg7, R10 + unsigned long arg8, 112(R1) + unsigned long *out1); 120(R1) + */ _GLOBAL(plpar_hcall_8arg_2ret) mfcr r0 + ld r11,STK_PARM(r11)(r1) /* put arg8 in R11 */ + stw r0,8(r1) - ld r11, 112(r1) /* put arg8 and out1 in R11 and R12 */ - ld r12, 120(r1) - - std r0,-8(r1) - stdu r1,-32(r1) + HVSC /* invoke the hypervisor */ - std r12,-8(r1) /* Save out ptr */ - - HVSC /* invoke the hypervisor */ - - ld r10,-8(r1) /* Fetch r4 ret arg */ - std r4,0(r10) - - ld r1,0(r1) - ld r0,-8(r1) + lwz r0,8(r1) + ld r10,STK_PARM(r12)(r1) /* Fetch r4 ret arg */ + std r4,0(r10) mtcrf 0xff,r0 - blr /* return r3 = status */ + blr /* return r3 = status */ -/* long plpar_hcall_4out(unsigned long opcode, R3 - unsigned long arg1, R4 - unsigned long arg2, R5 - unsigned long arg3, R6 - unsigned long arg4, R7 - unsigned long *out1, (r4) R8 - unsigned long *out2, (r5) R9 - unsigned long *out3, (r6) R10 - unsigned long *out4); (r7) 112(R1). From Parameter save area. +/* long plpar_hcall_4out(unsigned long opcode, R3 + unsigned long arg1, R4 + unsigned long arg2, R5 + unsigned long arg3, R6 + unsigned long arg4, R7 + unsigned long *out1, R8 + unsigned long *out2, R9 + unsigned long *out3, R10 + unsigned long *out4); 112(R1) */ _GLOBAL(plpar_hcall_4out) mfcr r0 - std r0,-8(r1) - ld r14,112(r1) - stdu r1,-48(r1) - - std r8,32(r1) /* Save out ptrs. */ - std r9,24(r1) - std r10,16(r1) - std r14,8(r1) - - HVSC /* invoke the hypervisor */ + stw r0,8(r1) - ld r14,32(r1) /* Fetch r4-r7 ret args. */ - std r4,0(r14) - ld r14,24(r1) - std r5,0(r14) - ld r14,16(r1) - std r6,0(r14) - ld r14,8(r1) - std r7,0(r14) + std r8,STK_PARM(r8)(r1) /* Save out ptrs */ + std r9,STK_PARM(r9)(r1) + std r10,STK_PARM(r10)(r1) + + HVSC /* invoke the hypervisor */ + + lwz r0,8(r1) + + ld r8,STK_PARM(r8)(r1) /* Fetch r4-r7 ret args */ + ld r9,STK_PARM(r9)(r1) + ld r10,STK_PARM(r10)(r1) + ld r11,STK_PARM(r11)(r1) + std r4,0(r8) + std r5,0(r9) + std r6,0(r10) + std r7,0(r11) - ld r1,0(r1) - ld r0,-8(r1) mtcrf 0xff,r0 - blr /* return r3 = status */ + blr /* return r3 = status */ diff -puN include/asm-ppc64/hvcall.h~ppc64-fix-pseries-hcall-stubs include/asm-ppc64/hvcall.h --- 25/include/asm-ppc64/hvcall.h~ppc64-fix-pseries-hcall-stubs 2005-03-21 21:54:09.000000000 -0800 +++ 25-akpm/include/asm-ppc64/hvcall.h 2005-03-21 21:54:09.000000000 -0800 @@ -1,6 +1,8 @@ #ifndef _PPC64_HVCALL_H #define _PPC64_HVCALL_H +#define HVSC .long 0x44000022 + #define H_Success 0 #define H_Busy 1 /* Hardware busy -- retry later */ #define H_Constrained 4 /* Resource request constrained to max allowed */ @@ -41,7 +43,7 @@ /* Flags */ #define H_LARGE_PAGE (1UL<<(63-16)) -#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ +#define H_EXACT (1UL<<(63-24)) /* Use exact PTE or return H_PTEG_FULL */ #define H_R_XLATE (1UL<<(63-25)) /* include a valid logical page num in the pte if the valid bit is set */ #define H_READ_4 (1UL<<(63-26)) /* Return 4 PTEs */ #define H_AVPN (1UL<<(63-32)) /* An avpn is provided as a sanity test */ @@ -54,8 +56,6 @@ #define H_PP1 (1UL<<(63-62)) #define H_PP2 (1UL<<(63-63)) - - /* pSeries hypervisor opcodes */ #define H_REMOVE 0x04 #define H_ENTER 0x08 @@ -108,6 +108,8 @@ #define H_FREE_VTERM 0x158 #define H_POLL_PENDING 0x1D8 +#ifndef __ASSEMBLY__ + /* plpar_hcall() -- Generic call interface using above opcodes * * The actual call interface is a hypervisor call instruction with @@ -125,8 +127,6 @@ long plpar_hcall(unsigned long opcode, unsigned long *out2, unsigned long *out3); -#define HVSC ".long 0x44000022\n" - /* Same as plpar_hcall but for those opcodes that return no values * other than status. Slightly more efficient. */ @@ -147,9 +147,6 @@ long plpar_hcall_8arg_2ret(unsigned long unsigned long arg7, unsigned long arg8, unsigned long *out1); - - - /* plpar_hcall_4out() * @@ -166,4 +163,5 @@ long plpar_hcall_4out(unsigned long opco unsigned long *out3, unsigned long *out4); +#endif /* __ASSEMBLY__ */ #endif /* _PPC64_HVCALL_H */ _