xref: /kvm-unit-tests/lib/s390x/sie.c (revision 93f65abcd96e37d41095110f2270d5c3760659bc)
1d75fac5fSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */
2d75fac5fSJanosch Frank /*
3ab68f968SJanosch Frank  * Library for managing various aspects of guests
4d75fac5fSJanosch Frank  *
5d75fac5fSJanosch Frank  * Copyright (c) 2021 IBM Corp
6d75fac5fSJanosch Frank  *
7d75fac5fSJanosch Frank  * Authors:
8d75fac5fSJanosch Frank  *  Janosch Frank <frankja@linux.ibm.com>
9d75fac5fSJanosch Frank  */
10d75fac5fSJanosch Frank 
11d75fac5fSJanosch Frank #include <asm/barrier.h>
124e53a1d0SJanosch Frank #include <bitops.h>
13d75fac5fSJanosch Frank #include <libcflat.h>
14d75fac5fSJanosch Frank #include <sie.h>
15a58e5546SJanosch Frank #include <asm/page.h>
16a58e5546SJanosch Frank #include <libcflat.h>
17a58e5546SJanosch Frank #include <alloc_page.h>
18d75fac5fSJanosch Frank 
191e19c3edSJanosch Frank void sie_expect_validity(struct vm *vm)
20d75fac5fSJanosch Frank {
211e19c3edSJanosch Frank 	vm->validity_expected = true;
22d75fac5fSJanosch Frank }
23d75fac5fSJanosch Frank 
241e19c3edSJanosch Frank uint16_t sie_get_validity(struct vm *vm)
25d75fac5fSJanosch Frank {
261e19c3edSJanosch Frank 	assert(vm->sblk->icptcode == ICPT_VALIDITY);
271e19c3edSJanosch Frank 	return vm->sblk->ipb >> 16;
281e19c3edSJanosch Frank }
291e19c3edSJanosch Frank 
301e19c3edSJanosch Frank void sie_check_validity(struct vm *vm, uint16_t vir_exp)
311e19c3edSJanosch Frank {
321e19c3edSJanosch Frank 	uint16_t vir = sie_get_validity(vm);
331e19c3edSJanosch Frank 
34d75fac5fSJanosch Frank 	report(vir_exp == vir, "VALIDITY: %x", vir);
35d75fac5fSJanosch Frank }
36d75fac5fSJanosch Frank 
37d75fac5fSJanosch Frank void sie_handle_validity(struct vm *vm)
38d75fac5fSJanosch Frank {
39d75fac5fSJanosch Frank 	if (vm->sblk->icptcode != ICPT_VALIDITY)
40d75fac5fSJanosch Frank 		return;
41d75fac5fSJanosch Frank 
421e19c3edSJanosch Frank 	if (!vm->validity_expected)
431e19c3edSJanosch Frank 		report_abort("VALIDITY: %x", sie_get_validity(vm));
441e19c3edSJanosch Frank 	vm->validity_expected = false;
45d75fac5fSJanosch Frank }
46a58e5546SJanosch Frank 
47ab68f968SJanosch Frank void sie(struct vm *vm)
48ab68f968SJanosch Frank {
49e9a5c8b6SJanosch Frank 	if (vm->sblk->sdf == 2)
50e9a5c8b6SJanosch Frank 		memcpy(vm->sblk->pv_grregs, vm->save_area.guest.grs,
51e9a5c8b6SJanosch Frank 		       sizeof(vm->save_area.guest.grs));
52e9a5c8b6SJanosch Frank 
53ab68f968SJanosch Frank 	/* Reset icptcode so we don't trip over it below */
54ab68f968SJanosch Frank 	vm->sblk->icptcode = 0;
55ab68f968SJanosch Frank 
56ab68f968SJanosch Frank 	while (vm->sblk->icptcode == 0) {
57ab68f968SJanosch Frank 		sie64a(vm->sblk, &vm->save_area);
58ab68f968SJanosch Frank 		sie_handle_validity(vm);
59ab68f968SJanosch Frank 	}
60ab68f968SJanosch Frank 	vm->save_area.guest.grs[14] = vm->sblk->gg14;
61ab68f968SJanosch Frank 	vm->save_area.guest.grs[15] = vm->sblk->gg15;
62e9a5c8b6SJanosch Frank 
63e9a5c8b6SJanosch Frank 	if (vm->sblk->sdf == 2)
64e9a5c8b6SJanosch Frank 		memcpy(vm->save_area.guest.grs, vm->sblk->pv_grregs,
65e9a5c8b6SJanosch Frank 		       sizeof(vm->save_area.guest.grs));
66ab68f968SJanosch Frank }
67ab68f968SJanosch Frank 
686d1cb286SJanosch Frank void sie_guest_sca_create(struct vm *vm)
696d1cb286SJanosch Frank {
706d1cb286SJanosch Frank 	vm->sca = (struct esca_block *)alloc_page();
716d1cb286SJanosch Frank 
726d1cb286SJanosch Frank 	/* Let's start out with one page of ESCA for now */
736d1cb286SJanosch Frank 	vm->sblk->scaoh = ((uint64_t)vm->sca >> 32);
746d1cb286SJanosch Frank 	vm->sblk->scaol = (uint64_t)vm->sca & ~0x3fU;
756d1cb286SJanosch Frank 	vm->sblk->ecb2 |= ECB2_ESCA;
764e53a1d0SJanosch Frank 
774e53a1d0SJanosch Frank 	/* Enable SIGP sense running interpretation */
784e53a1d0SJanosch Frank 	vm->sblk->ecb |= ECB_SRSI;
794e53a1d0SJanosch Frank 
804e53a1d0SJanosch Frank 	/* We assume that cpu 0 is always part of the vm */
814e53a1d0SJanosch Frank 	vm->sca->mcn[0] = BIT(63);
824e53a1d0SJanosch Frank 	vm->sca->cpu[0].sda = (uint64_t)vm->sblk;
836d1cb286SJanosch Frank }
846d1cb286SJanosch Frank 
85a58e5546SJanosch Frank /* Initializes the struct vm members like the SIE control block. */
86a58e5546SJanosch Frank void sie_guest_create(struct vm *vm, uint64_t guest_mem, uint64_t guest_mem_len)
87a58e5546SJanosch Frank {
88a58e5546SJanosch Frank 	vm->sblk = alloc_page();
89a58e5546SJanosch Frank 	memset(vm->sblk, 0, PAGE_SIZE);
90a58e5546SJanosch Frank 	vm->sblk->cpuflags = CPUSTAT_ZARCH | CPUSTAT_RUNNING;
91a58e5546SJanosch Frank 	vm->sblk->ihcpu = 0xffff;
92a58e5546SJanosch Frank 	vm->sblk->prefix = 0;
93a58e5546SJanosch Frank 
94a58e5546SJanosch Frank 	/* Guest memory chunks are always 1MB */
95a58e5546SJanosch Frank 	assert(!(guest_mem_len & ~HPAGE_MASK));
96*93f65abcSJanosch Frank 	vm->guest_mem = (uint8_t *)guest_mem;
979e3cff66SJanosch Frank 	/* For non-PV guests we re-use the host's ASCE for ease of use */
989e3cff66SJanosch Frank 	vm->save_area.guest.asce = stctg(1);
99a58e5546SJanosch Frank 	/* Currently MSO/MSL is the easiest option */
100a58e5546SJanosch Frank 	vm->sblk->mso = (uint64_t)guest_mem;
101a58e5546SJanosch Frank 	vm->sblk->msl = (uint64_t)guest_mem + ((guest_mem_len - 1) & HPAGE_MASK);
102a58e5546SJanosch Frank 
103a58e5546SJanosch Frank 	/* CRYCB needs to be in the first 2GB */
104a58e5546SJanosch Frank 	vm->crycb = alloc_pages_flags(0, AREA_DMA31);
105a58e5546SJanosch Frank 	vm->sblk->crycbd = (uint32_t)(uintptr_t)vm->crycb;
106a58e5546SJanosch Frank }
107a58e5546SJanosch Frank 
108a58e5546SJanosch Frank /* Frees the memory that was gathered on initialization */
109a58e5546SJanosch Frank void sie_guest_destroy(struct vm *vm)
110a58e5546SJanosch Frank {
111a58e5546SJanosch Frank 	free_page(vm->crycb);
112a58e5546SJanosch Frank 	free_page(vm->sblk);
1136d1cb286SJanosch Frank 	if (vm->sblk->ecb2 & ECB2_ESCA)
1146d1cb286SJanosch Frank 		free_page(vm->sca);
115a58e5546SJanosch Frank }
116