/* * 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) 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 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