summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powernv/opal-wrappers.S
blob: 54eca8b3b288f8fcca45ef5f44c5211832b3416f (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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
/*
 * PowerNV OPAL API wrappers
 *
 * 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>
#include <asm/jump_label.h>

	.section	".text"

#ifdef CONFIG_TRACEPOINTS
#ifdef HAVE_JUMP_LABEL
#define OPAL_BRANCH(LABEL)					\
	ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key)
#else

	.section	".toc","aw"

	.globl opal_tracepoint_refcount
opal_tracepoint_refcount:
	.llong	0

	.section	".text"

/*
 * We branch around this in early init by using an unconditional cpu
 * feature.
 */
#define OPAL_BRANCH(LABEL)					\
BEGIN_FTR_SECTION;						\
	b	1f;						\
END_FTR_SECTION(0, 1);						\
	ld	r12,opal_tracepoint_refcount@toc(r2);		\
	std	r12,32(r1);					\
	cmpdi	r12,0;						\
	bne-	LABEL;						\
1:

#endif

#else
#define OPAL_BRANCH(LABEL)
#endif

/* TODO:
 *
 * - Trace irqs in/off (needs saving/restoring all args, argh...)
 * - Get r11 feed up by Dave so I can have better register usage
 */

#define OPAL_CALL(name, token)		\
 _GLOBAL_TOC(name);			\
	mflr	r0;			\
	std	r0,16(r1);		\
	li	r0,token;		\
	OPAL_BRANCH(opal_tracepoint_entry) \
	mfcr	r12;			\
	stw	r12,8(r1);		\
	std	r1,PACAR1(r13);		\
	li	r11,0;			\
	mfmsr	r12;			\
	ori	r11,r11,MSR_EE;		\
	std	r12,PACASAVEDMSR(r13);	\
	andc	r12,r12,r11;		\
	mtmsrd	r12,1;			\
	LOAD_REG_ADDR(r11,opal_return);	\
	mtlr	r11;			\
	li	r11,MSR_DR|MSR_IR|MSR_LE;\
	andc	r12,r12,r11;		\
	mtspr	SPRN_HSRR1,r12;		\
	LOAD_REG_ADDR(r11,opal);	\
	ld	r12,8(r11);		\
	ld	r2,0(r11);		\
	mtspr	SPRN_HSRR0,r12;		\
	hrfid

opal_return:
	/*
	 * Fixup endian on OPAL return... we should be able to simplify
	 * this by instead converting the below trampoline to a set of
	 * bytes (always BE) since MSR:LE will end up fixed up as a side
	 * effect of the rfid.
	 */
	FIXUP_ENDIAN
	ld	r2,PACATOC(r13);
	lwz	r4,8(r1);
	ld	r5,16(r1);
	ld	r6,PACASAVEDMSR(r13);
	mtspr	SPRN_SRR0,r5;
	mtspr	SPRN_SRR1,r6;
	mtcr	r4;
	rfid

#ifdef CONFIG_TRACEPOINTS
opal_tracepoint_entry:
	stdu	r1,-STACKFRAMESIZE(r1)
	std	r0,STK_REG(R23)(r1)
	std	r3,STK_REG(R24)(r1)
	std	r4,STK_REG(R25)(r1)
	std	r5,STK_REG(R26)(r1)
	std	r6,STK_REG(R27)(r1)
	std	r7,STK_REG(R28)(r1)
	std	r8,STK_REG(R29)(r1)
	std	r9,STK_REG(R30)(r1)
	std	r10,STK_REG(R31)(r1)
	mr	r3,r0
	addi	r4,r1,STK_REG(R24)
	bl	__trace_opal_entry
	ld	r0,STK_REG(R23)(r1)
	ld	r3,STK_REG(R24)(r1)
	ld	r4,STK_REG(R25)(r1)
	ld	r5,STK_REG(R26)(r1)
	ld	r6,STK_REG(R27)(r1)
	ld	r7,STK_REG(R28)(r1)
	ld	r8,STK_REG(R29)(r1)
	ld	r9,STK_REG(R30)(r1)
	ld	r10,STK_REG(R31)(r1)
	LOAD_REG_ADDR(r11,opal_tracepoint_return)
	mfcr	r12
	std	r11,16(r1)
	stw	r12,8(r1)
	std	r1,PACAR1(r13)
	li	r11,0
	mfmsr	r12
	ori	r11,r11,MSR_EE
	std	r12,PACASAVEDMSR(r13)
	andc	r12,r12,r11
	mtmsrd	r12,1
	LOAD_REG_ADDR(r11,opal_return)
	mtlr	r11
	li	r11,MSR_DR|MSR_IR|MSR_LE
	andc	r12,r12,r11
	mtspr	SPRN_HSRR1,r12
	LOAD_REG_ADDR(r11,opal)
	ld	r12,8(r11)
	ld	r2,0(r11)
	mtspr	SPRN_HSRR0,r12
	hrfid

opal_tracepoint_return:
	std	r3,STK_REG(R31)(r1)
	mr	r4,r3
	ld	r0,STK_REG(R23)(r1)
	bl	__trace_opal_exit
	ld	r3,STK_REG(R31)(r1)
	addi	r1,r1,STACKFRAMESIZE
	ld	r0,16(r1)
	mtlr	r0
	blr
#endif

/*
 * Make opal call in realmode. This is a generic function to be called
 * from realmode. It handles endianness.
 *
 * r13 - paca pointer
 * r1  - stack pointer
 * r0  - opal token
 */
_GLOBAL(opal_call_realmode)
	mflr	r12
	std	r12,PPC_LR_STKOFF(r1)
	ld	r2,PACATOC(r13)
	/* Set opal return address */
	LOAD_REG_ADDR(r12,return_from_opal_call)
	mtlr	r12

	mfmsr	r12
#ifdef __LITTLE_ENDIAN__
	/* Handle endian-ness */
	li	r11,MSR_LE
	andc	r12,r12,r11
#endif
	mtspr	SPRN_HSRR1,r12
	LOAD_REG_ADDR(r11,opal)
	ld	r12,8(r11)
	ld	r2,0(r11)
	mtspr	SPRN_HSRR0,r12
	hrfid

return_from_opal_call:
#ifdef __LITTLE_ENDIAN__
	FIXUP_ENDIAN
#endif
	ld	r12,PPC_LR_STKOFF(r1)
	mtlr	r12
	blr

OPAL_CALL(opal_invalid_call,			OPAL_INVALID_CALL);
OPAL_CALL(opal_console_write,			OPAL_CONSOLE_WRITE);
OPAL_CALL(opal_console_read,			OPAL_CONSOLE_READ);
OPAL_CALL(opal_console_write_buffer_space,	OPAL_CONSOLE_WRITE_BUFFER_SPACE);
OPAL_CALL(opal_rtc_read,			OPAL_RTC_READ);
OPAL_CALL(opal_rtc_write,			OPAL_RTC_WRITE);
OPAL_CALL(opal_cec_power_down,			OPAL_CEC_POWER_DOWN);
OPAL_CALL(opal_cec_reboot,			OPAL_CEC_REBOOT);
OPAL_CALL(opal_read_nvram,			OPAL_READ_NVRAM);
OPAL_CALL(opal_write_nvram,			OPAL_WRITE_NVRAM);
OPAL_CALL(opal_handle_interrupt,		OPAL_HANDLE_INTERRUPT);
OPAL_CALL(opal_poll_events,			OPAL_POLL_EVENTS);
OPAL_CALL(opal_pci_set_hub_tce_memory,		OPAL_PCI_SET_HUB_TCE_MEMORY);
OPAL_CALL(opal_pci_set_phb_tce_memory,		OPAL_PCI_SET_PHB_TCE_MEMORY);
OPAL_CALL(opal_pci_config_read_byte,		OPAL_PCI_CONFIG_READ_BYTE);
OPAL_CALL(opal_pci_config_read_half_word,	OPAL_PCI_CONFIG_READ_HALF_WORD);
OPAL_CALL(opal_pci_config_read_word,		OPAL_PCI_CONFIG_READ_WORD);
OPAL_CALL(opal_pci_config_write_byte,		OPAL_PCI_CONFIG_WRITE_BYTE);
OPAL_CALL(opal_pci_config_write_half_word,	OPAL_PCI_CONFIG_WRITE_HALF_WORD);
OPAL_CALL(opal_pci_config_write_word,		OPAL_PCI_CONFIG_WRITE_WORD);
OPAL_CALL(opal_set_xive,			OPAL_SET_XIVE);
OPAL_CALL(opal_get_xive,			OPAL_GET_XIVE);
OPAL_CALL(opal_register_exception_handler,	OPAL_REGISTER_OPAL_EXCEPTION_HANDLER);
OPAL_CALL(opal_pci_eeh_freeze_status,		OPAL_PCI_EEH_FREEZE_STATUS);
OPAL_CALL(opal_pci_eeh_freeze_clear,		OPAL_PCI_EEH_FREEZE_CLEAR);
OPAL_CALL(opal_pci_eeh_freeze_set,		OPAL_PCI_EEH_FREEZE_SET);
OPAL_CALL(opal_pci_err_inject,			OPAL_PCI_ERR_INJECT);
OPAL_CALL(opal_pci_shpc,			OPAL_PCI_SHPC);
OPAL_CALL(opal_pci_phb_mmio_enable,		OPAL_PCI_PHB_MMIO_ENABLE);
OPAL_CALL(opal_pci_set_phb_mem_window,		OPAL_PCI_SET_PHB_MEM_WINDOW);
OPAL_CALL(opal_pci_map_pe_mmio_window,		OPAL_PCI_MAP_PE_MMIO_WINDOW);
OPAL_CALL(opal_pci_set_phb_table_memory,	OPAL_PCI_SET_PHB_TABLE_MEMORY);
OPAL_CALL(opal_pci_set_pe,			OPAL_PCI_SET_PE);
OPAL_CALL(opal_pci_set_peltv,			OPAL_PCI_SET_PELTV);
OPAL_CALL(opal_pci_set_mve,			OPAL_PCI_SET_MVE);
OPAL_CALL(opal_pci_set_mve_enable,		OPAL_PCI_SET_MVE_ENABLE);
OPAL_CALL(opal_pci_get_xive_reissue,		OPAL_PCI_GET_XIVE_REISSUE);
OPAL_CALL(opal_pci_set_xive_reissue,		OPAL_PCI_SET_XIVE_REISSUE);
OPAL_CALL(opal_pci_set_xive_pe,			OPAL_PCI_SET_XIVE_PE);
OPAL_CALL(opal_get_xive_source,			OPAL_GET_XIVE_SOURCE);
OPAL_CALL(opal_get_msi_32,			OPAL_GET_MSI_32);
OPAL_CALL(opal_get_msi_64,			OPAL_GET_MSI_64);
OPAL_CALL(opal_start_cpu,			OPAL_START_CPU);
OPAL_CALL(opal_query_cpu_status,		OPAL_QUERY_CPU_STATUS);
OPAL_CALL(opal_write_oppanel,			OPAL_WRITE_OPPANEL);
OPAL_CALL(opal_pci_map_pe_dma_window,		OPAL_PCI_MAP_PE_DMA_WINDOW);
OPAL_CALL(opal_pci_map_pe_dma_window_real,	OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
OPAL_CALL(opal_pci_reset,			OPAL_PCI_RESET);
OPAL_CALL(opal_pci_get_hub_diag_data,		OPAL_PCI_GET_HUB_DIAG_DATA);
OPAL_CALL(opal_pci_get_phb_diag_data,		OPAL_PCI_GET_PHB_DIAG_DATA);
OPAL_CALL(opal_pci_fence_phb,			OPAL_PCI_FENCE_PHB);
OPAL_CALL(opal_pci_reinit,			OPAL_PCI_REINIT);
OPAL_CALL(opal_pci_mask_pe_error,		OPAL_PCI_MASK_PE_ERROR);
OPAL_CALL(opal_set_slot_led_status,		OPAL_SET_SLOT_LED_STATUS);
OPAL_CALL(opal_get_epow_status,			OPAL_GET_EPOW_STATUS);
OPAL_CALL(opal_set_system_attention_led,	OPAL_SET_SYSTEM_ATTENTION_LED);
OPAL_CALL(opal_pci_next_error,			OPAL_PCI_NEXT_ERROR);
OPAL_CALL(opal_pci_poll,			OPAL_PCI_POLL);
OPAL_CALL(opal_pci_msi_eoi,			OPAL_PCI_MSI_EOI);
OPAL_CALL(opal_pci_get_phb_diag_data2,		OPAL_PCI_GET_PHB_DIAG_DATA2);
OPAL_CALL(opal_xscom_read,			OPAL_XSCOM_READ);
OPAL_CALL(opal_xscom_write,			OPAL_XSCOM_WRITE);
OPAL_CALL(opal_lpc_read,			OPAL_LPC_READ);
OPAL_CALL(opal_lpc_write,			OPAL_LPC_WRITE);
OPAL_CALL(opal_return_cpu,			OPAL_RETURN_CPU);
OPAL_CALL(opal_reinit_cpus,			OPAL_REINIT_CPUS);
OPAL_CALL(opal_read_elog,			OPAL_ELOG_READ);
OPAL_CALL(opal_send_ack_elog,			OPAL_ELOG_ACK);
OPAL_CALL(opal_get_elog_size,			OPAL_ELOG_SIZE);
OPAL_CALL(opal_resend_pending_logs,		OPAL_ELOG_RESEND);
OPAL_CALL(opal_write_elog,			OPAL_ELOG_WRITE);
OPAL_CALL(opal_validate_flash,			OPAL_FLASH_VALIDATE);
OPAL_CALL(opal_manage_flash,			OPAL_FLASH_MANAGE);
OPAL_CALL(opal_update_flash,			OPAL_FLASH_UPDATE);
OPAL_CALL(opal_resync_timebase,			OPAL_RESYNC_TIMEBASE);
OPAL_CALL(opal_check_token,			OPAL_CHECK_TOKEN);
OPAL_CALL(opal_dump_init,			OPAL_DUMP_INIT);
OPAL_CALL(opal_dump_info,			OPAL_DUMP_INFO);
OPAL_CALL(opal_dump_info2,			OPAL_DUMP_INFO2);
OPAL_CALL(opal_dump_read,			OPAL_DUMP_READ);
OPAL_CALL(opal_dump_ack,			OPAL_DUMP_ACK);
OPAL_CALL(opal_get_msg,				OPAL_GET_MSG);
OPAL_CALL(opal_check_completion,		OPAL_CHECK_ASYNC_COMPLETION);
OPAL_CALL(opal_dump_resend_notification,	OPAL_DUMP_RESEND);
OPAL_CALL(opal_sync_host_reboot,		OPAL_SYNC_HOST_REBOOT);
OPAL_CALL(opal_sensor_read,			OPAL_SENSOR_READ);
OPAL_CALL(opal_get_param,			OPAL_GET_PARAM);
OPAL_CALL(opal_set_param,			OPAL_SET_PARAM);
OPAL_CALL(opal_handle_hmi,			OPAL_HANDLE_HMI);
OPAL_CALL(opal_slw_set_reg,			OPAL_SLW_SET_REG);
OPAL_CALL(opal_register_dump_region,		OPAL_REGISTER_DUMP_REGION);
OPAL_CALL(opal_unregister_dump_region,		OPAL_UNREGISTER_DUMP_REGION);
OPAL_CALL(opal_pci_set_phb_cxl_mode,		OPAL_PCI_SET_PHB_CXL_MODE);
OPAL_CALL(opal_tpo_write,			OPAL_WRITE_TPO);
OPAL_CALL(opal_tpo_read,			OPAL_READ_TPO);
OPAL_CALL(opal_ipmi_send,			OPAL_IPMI_SEND);
OPAL_CALL(opal_ipmi_recv,			OPAL_IPMI_RECV);
OPAL_CALL(opal_i2c_request,			OPAL_I2C_REQUEST);