aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/platforms/powernv/opal-takeover.S
blob: 77b48b2b930946703387d6f3dd2e811b79c788f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
/*
 * 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 STK_PARAM(i)	(48 + ((i)-3)*8)

#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