xref: /kvm-unit-tests/lib/s390x/snippet.h (revision d1e2a8e2d0d5856f1a6ce23ea3f044a1532eab40)
1da96771eSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2da96771eSJanosch Frank /*
3da96771eSJanosch Frank  * Snippet definitions
4da96771eSJanosch Frank  *
5da96771eSJanosch Frank  * Copyright IBM Corp. 2021
6da96771eSJanosch Frank  * Author: Janosch Frank <frankja@linux.ibm.com>
7da96771eSJanosch Frank  */
8da96771eSJanosch Frank 
9da96771eSJanosch Frank #ifndef _S390X_SNIPPET_H_
10da96771eSJanosch Frank #define _S390X_SNIPPET_H_
11da96771eSJanosch Frank 
1273950a25SJanosch Frank #include <sie.h>
1373950a25SJanosch Frank #include <uv.h>
1473950a25SJanosch Frank #include <asm/uv.h>
1573950a25SJanosch Frank 
16da96771eSJanosch Frank /* This macro cuts down the length of the pointers to snippets */
17da96771eSJanosch Frank #define SNIPPET_NAME_START(type, file) \
18da96771eSJanosch Frank 	_binary_s390x_snippets_##type##_##file##_gbin_start
19da96771eSJanosch Frank #define SNIPPET_NAME_END(type, file) \
20da96771eSJanosch Frank 	_binary_s390x_snippets_##type##_##file##_gbin_end
21dc4f7106SJanosch Frank #define SNIPPET_HDR_START(type, file) \
22dc4f7106SJanosch Frank 	_binary_s390x_snippets_##type##_##file##_hdr_start
23dc4f7106SJanosch Frank #define SNIPPET_HDR_END(type, file) \
24dc4f7106SJanosch Frank 	_binary_s390x_snippets_##type##_##file##_hdr_end
25dc4f7106SJanosch Frank 
26da96771eSJanosch Frank 
27da96771eSJanosch Frank /* Returns the length of the snippet */
28da96771eSJanosch Frank #define SNIPPET_LEN(type, file) \
29da96771eSJanosch Frank 	((uintptr_t)SNIPPET_NAME_END(type, file) - (uintptr_t)SNIPPET_NAME_START(type, file))
30dc4f7106SJanosch Frank #define SNIPPET_HDR_LEN(type, file) \
31dc4f7106SJanosch Frank 	((uintptr_t)SNIPPET_HDR_END(type, file) - (uintptr_t)SNIPPET_HDR_START(type, file))
32da96771eSJanosch Frank 
33ec6683adSJanosch Frank /*
34ec6683adSJanosch Frank  * Some of the UV memory needs to be allocated with >31 bit
35ec6683adSJanosch Frank  * addresses which means we need a lot more memory than other
36ec6683adSJanosch Frank  * tests.
37ec6683adSJanosch Frank  */
38ec6683adSJanosch Frank #define SNIPPET_PV_MIN_MEM_SIZE	(SZ_1M * 2200UL)
39ec6683adSJanosch Frank 
4073950a25SJanosch Frank #define SNIPPET_PV_TWEAK0	0x42UL
4173950a25SJanosch Frank #define SNIPPET_PV_TWEAK1	0UL
42b36f35a8SJanosch Frank #define SNIPPET_UNPACK_OFF	0
4373950a25SJanosch Frank 
4473950a25SJanosch Frank 
45da96771eSJanosch Frank /*
46da96771eSJanosch Frank  * C snippet instructions start at 0x4000 due to the prefix and the
47da96771eSJanosch Frank  * stack being before that. ASM snippets don't strictly need a stack
48da96771eSJanosch Frank  * but keeping the starting address the same means less code.
49da96771eSJanosch Frank  */
50da96771eSJanosch Frank #define SNIPPET_ENTRY_ADDR 0x4000
51da96771eSJanosch Frank 
52da96771eSJanosch Frank /* Standard entry PSWs for snippets which can simply be copied into the guest PSW */
53da96771eSJanosch Frank static const struct psw snippet_psw = {
54da96771eSJanosch Frank 	.mask = PSW_MASK_64,
55da96771eSJanosch Frank 	.addr = SNIPPET_ENTRY_ADDR,
56da96771eSJanosch Frank };
5773950a25SJanosch Frank 
5873950a25SJanosch Frank /*
5973950a25SJanosch Frank  * Sets up a snippet guest on top of an existing and initialized SIE
6073950a25SJanosch Frank  * vm struct.
6173950a25SJanosch Frank  * Once this function has finished without errors the guest can be started.
6273950a25SJanosch Frank  *
6373950a25SJanosch Frank  * @vm: VM that this function will populated, has to be initialized already
6473950a25SJanosch Frank  * @gbin: Snippet gbin data pointer
6573950a25SJanosch Frank  * @gbin_len: Length of the gbin data
6673950a25SJanosch Frank  * @off: Offset from guest absolute 0x0 where snippet is copied to
6773950a25SJanosch Frank  */
snippet_init(struct vm * vm,const char * gbin,uint64_t gbin_len,uint64_t off)6873950a25SJanosch Frank static inline void snippet_init(struct vm *vm, const char *gbin,
6973950a25SJanosch Frank 				uint64_t gbin_len, uint64_t off)
7073950a25SJanosch Frank {
7173950a25SJanosch Frank 	uint64_t mso = vm->sblk->mso;
7273950a25SJanosch Frank 
7373950a25SJanosch Frank 	/* Copy test image to guest memory */
7473950a25SJanosch Frank 	memcpy((void *)mso + off, gbin, gbin_len);
7573950a25SJanosch Frank 
7673950a25SJanosch Frank 	/* Setup guest PSW */
7773950a25SJanosch Frank 	vm->sblk->gpsw = snippet_psw;
7873950a25SJanosch Frank 
7973950a25SJanosch Frank 	/*
8073950a25SJanosch Frank 	 * We want to exit on PGM exceptions so we don't need
8173950a25SJanosch Frank 	 * exception handlers in the guest.
8273950a25SJanosch Frank 	 */
8373950a25SJanosch Frank 	vm->sblk->ictl = ICTL_OPEREXC | ICTL_PINT;
8473950a25SJanosch Frank }
8573950a25SJanosch Frank 
8673950a25SJanosch Frank /*
8773950a25SJanosch Frank  * Sets up a snippet UV/PV guest on top of an existing and initialized
8873950a25SJanosch Frank  * SIE vm struct.
8973950a25SJanosch Frank  * Once this function has finished without errors the guest can be started.
9073950a25SJanosch Frank  *
9173950a25SJanosch Frank  * @vm: VM that this function will populated, has to be initialized already
9273950a25SJanosch Frank  * @gbin: Snippet gbin data pointer
9373950a25SJanosch Frank  * @hdr: Snippet SE header data pointer
9473950a25SJanosch Frank  * @gbin_len: Length of the gbin data
9573950a25SJanosch Frank  * @hdr_len: Length of the hdr data
9673950a25SJanosch Frank  * @off: Offset from guest absolute 0x0 where snippet is copied to
9773950a25SJanosch Frank  */
snippet_pv_init(struct vm * vm,const char * gbin,const char * hdr,uint64_t gbin_len,uint64_t hdr_len,uint64_t off)9873950a25SJanosch Frank static inline void snippet_pv_init(struct vm *vm, const char *gbin,
9973950a25SJanosch Frank 				   const char *hdr, uint64_t gbin_len,
10073950a25SJanosch Frank 				   uint64_t hdr_len, uint64_t off)
10173950a25SJanosch Frank {
10273950a25SJanosch Frank 	uint64_t tweak[2] = {SNIPPET_PV_TWEAK0, SNIPPET_PV_TWEAK1};
10373950a25SJanosch Frank 	uint64_t mso = vm->sblk->mso;
10473950a25SJanosch Frank 	int i;
10573950a25SJanosch Frank 
10673950a25SJanosch Frank 	snippet_init(vm, gbin, gbin_len, off);
10773950a25SJanosch Frank 
10873950a25SJanosch Frank 	uv_create_guest(vm);
10973950a25SJanosch Frank 	uv_set_se_hdr(vm->uv.vm_handle, (void *)hdr, hdr_len);
11073950a25SJanosch Frank 
11173950a25SJanosch Frank 	/* Unpack works on guest addresses so we only need off */
11273950a25SJanosch Frank 	uv_unpack(vm, off, gbin_len, tweak[0]);
11373950a25SJanosch Frank 	uv_verify_load(vm);
11473950a25SJanosch Frank 
11573950a25SJanosch Frank 	/*
11673950a25SJanosch Frank 	 * Manually import:
11773950a25SJanosch Frank 	 * - lowcore 0x0 - 0x1000 (asm)
11873950a25SJanosch Frank 	 * - stack 0x3000 (C)
11973950a25SJanosch Frank 	 */
12073950a25SJanosch Frank 	for (i = 0; i < 4; i++) {
12173950a25SJanosch Frank 		uv_import(vm->uv.vm_handle, mso + PAGE_SIZE * i);
12273950a25SJanosch Frank 	}
12373950a25SJanosch Frank }
12473950a25SJanosch Frank 
12573950a25SJanosch Frank /* Allocates and sets up a snippet based guest */
snippet_setup_guest(struct vm * vm,bool is_pv)12673950a25SJanosch Frank static inline void snippet_setup_guest(struct vm *vm, bool is_pv)
12773950a25SJanosch Frank {
128*ae337a39SNico Boehr 	const unsigned long guest_size = SZ_1M;
129*ae337a39SNico Boehr 	uint8_t *guest_start = sie_guest_alloc(guest_size);
13073950a25SJanosch Frank 
13173950a25SJanosch Frank 	/* Initialize the vm struct and allocate control blocks */
132*ae337a39SNico Boehr 	sie_guest_create(vm, (uint64_t)guest_start, guest_size);
13373950a25SJanosch Frank 
13473950a25SJanosch Frank 	if (is_pv) {
13573950a25SJanosch Frank 		/* FMT4 needs a ESCA */
13673950a25SJanosch Frank 		sie_guest_sca_create(vm);
13773950a25SJanosch Frank 
13873950a25SJanosch Frank 		/*
13973950a25SJanosch Frank 		 * Initialize UV and setup the address spaces needed
14073950a25SJanosch Frank 		 * to run a PV guest.
14173950a25SJanosch Frank 		 */
14273950a25SJanosch Frank 		uv_init();
14373950a25SJanosch Frank 		uv_setup_asces();
14473950a25SJanosch Frank 	}
14573950a25SJanosch Frank }
14673950a25SJanosch Frank 
147da96771eSJanosch Frank #endif
148