mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
752a6422fe
Some of the assembler files in lib/ make use of the fact that in the ELFv1 ABI, the caller guarantees to provide stack space to save the parameter registers r3 ... r10. This guarantee is no longer present in ELFv2 for functions that have no variable argument list and no more than 8 arguments. Change the affected routines to temporarily store registers in the red zone and/or the top of their own stack frame (in the space provided to save r31 .. r29, which is actually not used in these routines). In opal_query_takeover, simply always allocate a stack frame; the routine is not performance critical. Signed-off-by: Ulrich Weigand <ulrich.weigand@de.ibm.com> Signed-off-by: Anton Blanchard <anton@samba.org>
141 lines
2.6 KiB
ArmAsm
141 lines
2.6 KiB
ArmAsm
/*
|
|
* PowerNV OPAL takeover assembly code, for use by prom_init.c
|
|
*
|
|
* Copyright 2011 IBM Corp.
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version
|
|
* 2 of the License, or (at your option) any later version.
|
|
*/
|
|
|
|
#include <asm/ppc_asm.h>
|
|
#include <asm/hvcall.h>
|
|
#include <asm/asm-offsets.h>
|
|
#include <asm/opal.h>
|
|
|
|
#define H_HAL_TAKEOVER 0x5124
|
|
#define H_HAL_TAKEOVER_QUERY_MAGIC -1
|
|
|
|
.text
|
|
_GLOBAL(opal_query_takeover)
|
|
mfcr r0
|
|
stw r0,8(r1)
|
|
stdu r1,-STACKFRAMESIZE(r1)
|
|
std r3,STK_PARAM(R3)(r1)
|
|
std r4,STK_PARAM(R4)(r1)
|
|
li r3,H_HAL_TAKEOVER
|
|
li r4,H_HAL_TAKEOVER_QUERY_MAGIC
|
|
HVSC
|
|
addi r1,r1,STACKFRAMESIZE
|
|
ld r10,STK_PARAM(R3)(r1)
|
|
std r4,0(r10)
|
|
ld r10,STK_PARAM(R4)(r1)
|
|
std r5,0(r10)
|
|
lwz r0,8(r1)
|
|
mtcrf 0xff,r0
|
|
blr
|
|
|
|
_GLOBAL(opal_do_takeover)
|
|
mfcr r0
|
|
stw r0,8(r1)
|
|
mflr r0
|
|
std r0,16(r1)
|
|
bl __opal_do_takeover
|
|
ld r0,16(r1)
|
|
mtlr r0
|
|
lwz r0,8(r1)
|
|
mtcrf 0xff,r0
|
|
blr
|
|
|
|
__opal_do_takeover:
|
|
ld r4,0(r3)
|
|
ld r5,0x8(r3)
|
|
ld r6,0x10(r3)
|
|
ld r7,0x18(r3)
|
|
ld r8,0x20(r3)
|
|
ld r9,0x28(r3)
|
|
ld r10,0x30(r3)
|
|
ld r11,0x38(r3)
|
|
li r3,H_HAL_TAKEOVER
|
|
HVSC
|
|
blr
|
|
|
|
.globl opal_secondary_entry
|
|
opal_secondary_entry:
|
|
mr r31,r3
|
|
mfmsr r11
|
|
li r12,(MSR_SF | MSR_ISF)@highest
|
|
sldi r12,r12,48
|
|
or r11,r11,r12
|
|
mtmsrd r11
|
|
isync
|
|
mfspr r4,SPRN_PIR
|
|
std r4,0(r3)
|
|
1: HMT_LOW
|
|
ld r4,8(r3)
|
|
cmpli cr0,r4,0
|
|
beq 1b
|
|
HMT_MEDIUM
|
|
1: addi r3,r31,16
|
|
bl __opal_do_takeover
|
|
b 1b
|
|
|
|
_GLOBAL(opal_enter_rtas)
|
|
mflr r0
|
|
std r0,16(r1)
|
|
stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
|
|
|
|
/* Because PROM is running in 32b mode, it clobbers the high order half
|
|
* of all registers that it saves. We therefore save those registers
|
|
* PROM might touch to the stack. (r0, r3-r13 are caller saved)
|
|
*/
|
|
SAVE_GPR(2, r1)
|
|
SAVE_GPR(13, r1)
|
|
SAVE_8GPRS(14, r1)
|
|
SAVE_10GPRS(22, r1)
|
|
mfcr r10
|
|
mfmsr r11
|
|
std r10,_CCR(r1)
|
|
std r11,_MSR(r1)
|
|
|
|
/* Get the PROM entrypoint */
|
|
mtlr r5
|
|
|
|
/* Switch MSR to 32 bits mode
|
|
*/
|
|
li r12,1
|
|
rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
|
|
andc r11,r11,r12
|
|
li r12,1
|
|
rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
|
|
andc r11,r11,r12
|
|
mtmsrd r11
|
|
isync
|
|
|
|
/* Enter RTAS here... */
|
|
blrl
|
|
|
|
/* Just make sure that r1 top 32 bits didn't get
|
|
* corrupt by OF
|
|
*/
|
|
rldicl r1,r1,0,32
|
|
|
|
/* Restore the MSR (back to 64 bits) */
|
|
ld r0,_MSR(r1)
|
|
MTMSRD(r0)
|
|
isync
|
|
|
|
/* Restore other registers */
|
|
REST_GPR(2, r1)
|
|
REST_GPR(13, r1)
|
|
REST_8GPRS(14, r1)
|
|
REST_10GPRS(22, r1)
|
|
ld r4,_CCR(r1)
|
|
mtcr r4
|
|
|
|
addi r1,r1,PROM_FRAME_SIZE
|
|
ld r0,16(r1)
|
|
mtlr r0
|
|
blr
|