cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hvCall.S (6912B)


      1/* SPDX-License-Identifier: GPL-2.0-or-later */
      2/*
      3 * This file contains the generic code to perform a call to the
      4 * pSeries LPAR hypervisor.
      5 */
      6#include <linux/jump_label.h>
      7#include <asm/hvcall.h>
      8#include <asm/processor.h>
      9#include <asm/ppc_asm.h>
     10#include <asm/asm-offsets.h>
     11#include <asm/ptrace.h>
     12#include <asm/feature-fixups.h>
     13
     14	.section	".text"
     15	
     16#ifdef CONFIG_TRACEPOINTS
     17
     18#ifndef CONFIG_JUMP_LABEL
     19	.section	".toc","aw"
     20
     21	.globl hcall_tracepoint_refcount
     22hcall_tracepoint_refcount:
     23	.8byte	0
     24
     25	.section	".text"
     26#endif
     27
     28/*
     29 * precall must preserve all registers.  use unused STK_PARAM()
     30 * areas to save snapshots and opcode.
     31 */
     32#define HCALL_INST_PRECALL(FIRST_REG)				\
     33	mflr	r0;						\
     34	std	r3,STK_PARAM(R3)(r1);				\
     35	std	r4,STK_PARAM(R4)(r1);				\
     36	std	r5,STK_PARAM(R5)(r1);				\
     37	std	r6,STK_PARAM(R6)(r1);				\
     38	std	r7,STK_PARAM(R7)(r1);				\
     39	std	r8,STK_PARAM(R8)(r1);				\
     40	std	r9,STK_PARAM(R9)(r1);				\
     41	std	r10,STK_PARAM(R10)(r1);				\
     42	std	r0,16(r1);					\
     43	addi	r4,r1,STK_PARAM(FIRST_REG);			\
     44	stdu	r1,-STACK_FRAME_OVERHEAD(r1);			\
     45	bl	__trace_hcall_entry;				\
     46	ld	r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
     47	ld	r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1);	\
     48	ld	r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1);	\
     49	ld	r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1);	\
     50	ld	r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1);	\
     51	ld	r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1);	\
     52	ld	r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1);	\
     53	ld	r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1)
     54
     55/*
     56 * postcall is performed immediately before function return which
     57 * allows liberal use of volatile registers.
     58 */
     59#define __HCALL_INST_POSTCALL					\
     60	ld	r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
     61	std	r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1);	\
     62	mr	r4,r3;						\
     63	mr	r3,r0;						\
     64	bl	__trace_hcall_exit;				\
     65	ld	r0,STACK_FRAME_OVERHEAD+16(r1);			\
     66	addi	r1,r1,STACK_FRAME_OVERHEAD;			\
     67	ld	r3,STK_PARAM(R3)(r1);				\
     68	mtlr	r0
     69
     70#define HCALL_INST_POSTCALL_NORETS				\
     71	li	r5,0;						\
     72	__HCALL_INST_POSTCALL
     73
     74#define HCALL_INST_POSTCALL(BUFREG)				\
     75	mr	r5,BUFREG;					\
     76	__HCALL_INST_POSTCALL
     77
     78#ifdef CONFIG_JUMP_LABEL
     79#define HCALL_BRANCH(LABEL)					\
     80	ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key)
     81#else
     82
     83/*
     84 * We branch around this in early init (eg when populating the MMU
     85 * hashtable) by using an unconditional cpu feature.
     86 */
     87#define HCALL_BRANCH(LABEL)					\
     88BEGIN_FTR_SECTION;						\
     89	b	1f;						\
     90END_FTR_SECTION(0, 1);						\
     91	ld	r12,hcall_tracepoint_refcount@toc(r2);		\
     92	std	r12,32(r1);					\
     93	cmpdi	r12,0;						\
     94	bne-	LABEL;						\
     951:
     96#endif
     97
     98#else
     99#define HCALL_INST_PRECALL(FIRST_ARG)
    100#define HCALL_INST_POSTCALL_NORETS
    101#define HCALL_INST_POSTCALL(BUFREG)
    102#define HCALL_BRANCH(LABEL)
    103#endif
    104
    105_GLOBAL_TOC(plpar_hcall_norets_notrace)
    106	HMT_MEDIUM
    107
    108	mfcr	r0
    109	stw	r0,8(r1)
    110	HVSC				/* invoke the hypervisor */
    111
    112	li	r4,0
    113	stb	r4,PACASRR_VALID(r13)
    114
    115	lwz	r0,8(r1)
    116	mtcrf	0xff,r0
    117	blr				/* return r3 = status */
    118
    119_GLOBAL_TOC(plpar_hcall_norets)
    120	HMT_MEDIUM
    121
    122	mfcr	r0
    123	stw	r0,8(r1)
    124	HCALL_BRANCH(plpar_hcall_norets_trace)
    125	HVSC				/* invoke the hypervisor */
    126
    127	li	r4,0
    128	stb	r4,PACASRR_VALID(r13)
    129
    130	lwz	r0,8(r1)
    131	mtcrf	0xff,r0
    132	blr				/* return r3 = status */
    133
    134#ifdef CONFIG_TRACEPOINTS
    135plpar_hcall_norets_trace:
    136	HCALL_INST_PRECALL(R4)
    137	HVSC
    138	HCALL_INST_POSTCALL_NORETS
    139
    140	li	r4,0
    141	stb	r4,PACASRR_VALID(r13)
    142
    143	lwz	r0,8(r1)
    144	mtcrf	0xff,r0
    145	blr
    146#endif
    147
    148_GLOBAL_TOC(plpar_hcall)
    149	HMT_MEDIUM
    150
    151	mfcr	r0
    152	stw	r0,8(r1)
    153
    154	HCALL_BRANCH(plpar_hcall_trace)
    155
    156	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
    157
    158	mr	r4,r5
    159	mr	r5,r6
    160	mr	r6,r7
    161	mr	r7,r8
    162	mr	r8,r9
    163	mr	r9,r10
    164
    165	HVSC				/* invoke the hypervisor */
    166
    167	ld	r12,STK_PARAM(R4)(r1)
    168	std	r4,  0(r12)
    169	std	r5,  8(r12)
    170	std	r6, 16(r12)
    171	std	r7, 24(r12)
    172
    173	li	r4,0
    174	stb	r4,PACASRR_VALID(r13)
    175
    176	lwz	r0,8(r1)
    177	mtcrf	0xff,r0
    178
    179	blr				/* return r3 = status */
    180
    181#ifdef CONFIG_TRACEPOINTS
    182plpar_hcall_trace:
    183	HCALL_INST_PRECALL(R5)
    184
    185	std	r4,STK_PARAM(R4)(r1)
    186	mr	r0,r4
    187
    188	mr	r4,r5
    189	mr	r5,r6
    190	mr	r6,r7
    191	mr	r7,r8
    192	mr	r8,r9
    193	mr	r9,r10
    194
    195	HVSC
    196
    197	ld	r12,STK_PARAM(R4)(r1)
    198	std	r4,0(r12)
    199	std	r5,8(r12)
    200	std	r6,16(r12)
    201	std	r7,24(r12)
    202
    203	HCALL_INST_POSTCALL(r12)
    204
    205	li	r4,0
    206	stb	r4,PACASRR_VALID(r13)
    207
    208	lwz	r0,8(r1)
    209	mtcrf	0xff,r0
    210
    211	blr
    212#endif
    213
    214/*
    215 * plpar_hcall_raw can be called in real mode. kexec/kdump need some
    216 * hypervisor calls to be executed in real mode. So plpar_hcall_raw
    217 * does not access the per cpu hypervisor call statistics variables,
    218 * since these variables may not be present in the RMO region.
    219 */
    220_GLOBAL(plpar_hcall_raw)
    221	HMT_MEDIUM
    222
    223	mfcr	r0
    224	stw	r0,8(r1)
    225
    226	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
    227
    228	mr	r4,r5
    229	mr	r5,r6
    230	mr	r6,r7
    231	mr	r7,r8
    232	mr	r8,r9
    233	mr	r9,r10
    234
    235	HVSC				/* invoke the hypervisor */
    236
    237	ld	r12,STK_PARAM(R4)(r1)
    238	std	r4,  0(r12)
    239	std	r5,  8(r12)
    240	std	r6, 16(r12)
    241	std	r7, 24(r12)
    242
    243	li	r4,0
    244	stb	r4,PACASRR_VALID(r13)
    245
    246	lwz	r0,8(r1)
    247	mtcrf	0xff,r0
    248
    249	blr				/* return r3 = status */
    250
    251_GLOBAL_TOC(plpar_hcall9)
    252	HMT_MEDIUM
    253
    254	mfcr	r0
    255	stw	r0,8(r1)
    256
    257	HCALL_BRANCH(plpar_hcall9_trace)
    258
    259	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
    260
    261	mr	r4,r5
    262	mr	r5,r6
    263	mr	r6,r7
    264	mr	r7,r8
    265	mr	r8,r9
    266	mr	r9,r10
    267	ld	r10,STK_PARAM(R11)(r1)	 /* put arg7 in R10 */
    268	ld	r11,STK_PARAM(R12)(r1)	 /* put arg8 in R11 */
    269	ld	r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
    270
    271	HVSC				/* invoke the hypervisor */
    272
    273	mr	r0,r12
    274	ld	r12,STK_PARAM(R4)(r1)
    275	std	r4,  0(r12)
    276	std	r5,  8(r12)
    277	std	r6, 16(r12)
    278	std	r7, 24(r12)
    279	std	r8, 32(r12)
    280	std	r9, 40(r12)
    281	std	r10,48(r12)
    282	std	r11,56(r12)
    283	std	r0, 64(r12)
    284
    285	li	r4,0
    286	stb	r4,PACASRR_VALID(r13)
    287
    288	lwz	r0,8(r1)
    289	mtcrf	0xff,r0
    290
    291	blr				/* return r3 = status */
    292
    293#ifdef CONFIG_TRACEPOINTS
    294plpar_hcall9_trace:
    295	HCALL_INST_PRECALL(R5)
    296
    297	std	r4,STK_PARAM(R4)(r1)
    298	mr	r0,r4
    299
    300	mr	r4,r5
    301	mr	r5,r6
    302	mr	r6,r7
    303	mr	r7,r8
    304	mr	r8,r9
    305	mr	r9,r10
    306	ld	r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1)
    307	ld	r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1)
    308	ld	r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1)
    309
    310	HVSC
    311
    312	mr	r0,r12
    313	ld	r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1)
    314	std	r4,0(r12)
    315	std	r5,8(r12)
    316	std	r6,16(r12)
    317	std	r7,24(r12)
    318	std	r8,32(r12)
    319	std	r9,40(r12)
    320	std	r10,48(r12)
    321	std	r11,56(r12)
    322	std	r0,64(r12)
    323
    324	HCALL_INST_POSTCALL(r12)
    325
    326	li	r4,0
    327	stb	r4,PACASRR_VALID(r13)
    328
    329	lwz	r0,8(r1)
    330	mtcrf	0xff,r0
    331
    332	blr
    333#endif
    334
    335/* See plpar_hcall_raw to see why this is needed */
    336_GLOBAL(plpar_hcall9_raw)
    337	HMT_MEDIUM
    338
    339	mfcr	r0
    340	stw	r0,8(r1)
    341
    342	std     r4,STK_PARAM(R4)(r1)     /* Save ret buffer */
    343
    344	mr	r4,r5
    345	mr	r5,r6
    346	mr	r6,r7
    347	mr	r7,r8
    348	mr	r8,r9
    349	mr	r9,r10
    350	ld	r10,STK_PARAM(R11)(r1)	 /* put arg7 in R10 */
    351	ld	r11,STK_PARAM(R12)(r1)	 /* put arg8 in R11 */
    352	ld	r12,STK_PARAM(R13)(r1)    /* put arg9 in R12 */
    353
    354	HVSC				/* invoke the hypervisor */
    355
    356	mr	r0,r12
    357	ld	r12,STK_PARAM(R4)(r1)
    358	std	r4,  0(r12)
    359	std	r5,  8(r12)
    360	std	r6, 16(r12)
    361	std	r7, 24(r12)
    362	std	r8, 32(r12)
    363	std	r9, 40(r12)
    364	std	r10,48(r12)
    365	std	r11,56(r12)
    366	std	r0, 64(r12)
    367
    368	li	r4,0
    369	stb	r4,PACASRR_VALID(r13)
    370
    371	lwz	r0,8(r1)
    372	mtcrf	0xff,r0
    373
    374	blr				/* return r3 = status */