162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2015, Cyril Bur, IBM Corp.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "basic_asm.h"
762306a36Sopenharmony_ci#include "vmx_asm.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci# Should be safe from C, only touches r4, r5 and v0,v1,v2
1062306a36Sopenharmony_ciFUNC_START(check_vmx)
1162306a36Sopenharmony_ci	PUSH_BASIC_STACK(32)
1262306a36Sopenharmony_ci	mr r4,r3
1362306a36Sopenharmony_ci	li	r3,1 # assume a bad result
1462306a36Sopenharmony_ci	li	r5,0
1562306a36Sopenharmony_ci	lvx	v0,r5,r4
1662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v20
1762306a36Sopenharmony_ci	vmr	v2,v1
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci	addi	r5,r5,16
2062306a36Sopenharmony_ci	lvx	v0,r5,r4
2162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v21
2262306a36Sopenharmony_ci	vand	v2,v2,v1
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	addi	r5,r5,16
2562306a36Sopenharmony_ci	lvx	v0,r5,r4
2662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v22
2762306a36Sopenharmony_ci	vand	v2,v2,v1
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	addi	r5,r5,16
3062306a36Sopenharmony_ci	lvx	v0,r5,r4
3162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v23
3262306a36Sopenharmony_ci	vand	v2,v2,v1
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	addi	r5,r5,16
3562306a36Sopenharmony_ci	lvx	v0,r5,r4
3662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v24
3762306a36Sopenharmony_ci	vand	v2,v2,v1
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	addi	r5,r5,16
4062306a36Sopenharmony_ci	lvx	v0,r5,r4
4162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v25
4262306a36Sopenharmony_ci	vand	v2,v2,v1
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	addi	r5,r5,16
4562306a36Sopenharmony_ci	lvx	v0,r5,r4
4662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v26
4762306a36Sopenharmony_ci	vand	v2,v2,v1
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	addi	r5,r5,16
5062306a36Sopenharmony_ci	lvx	v0,r5,r4
5162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v27
5262306a36Sopenharmony_ci	vand	v2,v2,v1
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci	addi	r5,r5,16
5562306a36Sopenharmony_ci	lvx	v0,r5,r4
5662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v28
5762306a36Sopenharmony_ci	vand	v2,v2,v1
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	addi	r5,r5,16
6062306a36Sopenharmony_ci	lvx	v0,r5,r4
6162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v29
6262306a36Sopenharmony_ci	vand	v2,v2,v1
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	addi	r5,r5,16
6562306a36Sopenharmony_ci	lvx	v0,r5,r4
6662306a36Sopenharmony_ci	vcmpequd.	v1,v0,v30
6762306a36Sopenharmony_ci	vand	v2,v2,v1
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	addi	r5,r5,16
7062306a36Sopenharmony_ci	lvx	v0,r5,r4
7162306a36Sopenharmony_ci	vcmpequd.	v1,v0,v31
7262306a36Sopenharmony_ci	vand	v2,v2,v1
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	li	r5,STACK_FRAME_LOCAL(0,0)
7562306a36Sopenharmony_ci	stvx	v2,r5,sp
7662306a36Sopenharmony_ci	ldx	r0,r5,sp
7762306a36Sopenharmony_ci	cmpdi	r0,0xffffffffffffffff
7862306a36Sopenharmony_ci	bne	1f
7962306a36Sopenharmony_ci	li	r3,0
8062306a36Sopenharmony_ci1:	POP_BASIC_STACK(32)
8162306a36Sopenharmony_ci	blr
8262306a36Sopenharmony_ciFUNC_END(check_vmx)
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci# Safe from C
8562306a36Sopenharmony_ciFUNC_START(test_vmx)
8662306a36Sopenharmony_ci	# r3 holds pointer to where to put the result of fork
8762306a36Sopenharmony_ci	# r4 holds pointer to the pid
8862306a36Sopenharmony_ci	# v20-v31 are non-volatile
8962306a36Sopenharmony_ci	PUSH_BASIC_STACK(512)
9062306a36Sopenharmony_ci	std	r3,STACK_FRAME_PARAM(0)(sp) # Address of varray
9162306a36Sopenharmony_ci	std r4,STACK_FRAME_PARAM(1)(sp) # address of pid
9262306a36Sopenharmony_ci	PUSH_VMX(STACK_FRAME_LOCAL(2,0),r4)
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	bl load_vmx
9562306a36Sopenharmony_ci	nop
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	li	r0,__NR_fork
9862306a36Sopenharmony_ci	sc
9962306a36Sopenharmony_ci	# Pass the result of fork back to the caller
10062306a36Sopenharmony_ci	ld	r9,STACK_FRAME_PARAM(1)(sp)
10162306a36Sopenharmony_ci	std	r3,0(r9)
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	ld r3,STACK_FRAME_PARAM(0)(sp)
10462306a36Sopenharmony_ci	bl check_vmx
10562306a36Sopenharmony_ci	nop
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	POP_VMX(STACK_FRAME_LOCAL(2,0),r4)
10862306a36Sopenharmony_ci	POP_BASIC_STACK(512)
10962306a36Sopenharmony_ci	blr
11062306a36Sopenharmony_ciFUNC_END(test_vmx)
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci# int preempt_vmx(vector int *varray, int *threads_starting, int *running)
11362306a36Sopenharmony_ci# On starting will (atomically) decrement threads_starting as a signal that
11462306a36Sopenharmony_ci# the VMX have been loaded with varray. Will proceed to check the validity of
11562306a36Sopenharmony_ci# the VMX registers while running is not zero.
11662306a36Sopenharmony_ciFUNC_START(preempt_vmx)
11762306a36Sopenharmony_ci	PUSH_BASIC_STACK(512)
11862306a36Sopenharmony_ci	std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
11962306a36Sopenharmony_ci	std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
12062306a36Sopenharmony_ci	std r5,STACK_FRAME_PARAM(2)(sp) # int *running
12162306a36Sopenharmony_ci	# VMX need to write to 16 byte aligned addresses, skip STACK_FRAME_LOCAL(3,0)
12262306a36Sopenharmony_ci	PUSH_VMX(STACK_FRAME_LOCAL(4,0),r4)
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	bl load_vmx
12562306a36Sopenharmony_ci	nop
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	sync
12862306a36Sopenharmony_ci	# Atomic DEC
12962306a36Sopenharmony_ci	ld r3,STACK_FRAME_PARAM(1)(sp)
13062306a36Sopenharmony_ci1:	lwarx r4,0,r3
13162306a36Sopenharmony_ci	addi r4,r4,-1
13262306a36Sopenharmony_ci	stwcx. r4,0,r3
13362306a36Sopenharmony_ci	bne- 1b
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci2:	ld r3,STACK_FRAME_PARAM(0)(sp)
13662306a36Sopenharmony_ci	bl check_vmx
13762306a36Sopenharmony_ci	nop
13862306a36Sopenharmony_ci	cmpdi r3,0
13962306a36Sopenharmony_ci	bne 3f
14062306a36Sopenharmony_ci	ld r4,STACK_FRAME_PARAM(2)(sp)
14162306a36Sopenharmony_ci	ld r5,0(r4)
14262306a36Sopenharmony_ci	cmpwi r5,0
14362306a36Sopenharmony_ci	bne 2b
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci3:	POP_VMX(STACK_FRAME_LOCAL(4,0),r4)
14662306a36Sopenharmony_ci	POP_BASIC_STACK(512)
14762306a36Sopenharmony_ci	blr
14862306a36Sopenharmony_ciFUNC_END(preempt_vmx)
149