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