1d75fac5fSJanosch Frank /* SPDX-License-Identifier: GPL-2.0-only */ 2d75fac5fSJanosch Frank /* 3*ab68f968SJanosch 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> 12d75fac5fSJanosch Frank #include <libcflat.h> 13d75fac5fSJanosch Frank #include <sie.h> 14a58e5546SJanosch Frank #include <asm/page.h> 15a58e5546SJanosch Frank #include <libcflat.h> 16a58e5546SJanosch Frank #include <alloc_page.h> 17d75fac5fSJanosch Frank 18d75fac5fSJanosch Frank static bool validity_expected; 19d75fac5fSJanosch Frank static uint16_t vir; /* Validity interception reason */ 20d75fac5fSJanosch Frank 21d75fac5fSJanosch Frank void sie_expect_validity(void) 22d75fac5fSJanosch Frank { 23d75fac5fSJanosch Frank validity_expected = true; 24d75fac5fSJanosch Frank vir = 0; 25d75fac5fSJanosch Frank } 26d75fac5fSJanosch Frank 27d75fac5fSJanosch Frank void sie_check_validity(uint16_t vir_exp) 28d75fac5fSJanosch Frank { 29d75fac5fSJanosch Frank report(vir_exp == vir, "VALIDITY: %x", vir); 30d75fac5fSJanosch Frank vir = 0; 31d75fac5fSJanosch Frank } 32d75fac5fSJanosch Frank 33d75fac5fSJanosch Frank void sie_handle_validity(struct vm *vm) 34d75fac5fSJanosch Frank { 35d75fac5fSJanosch Frank if (vm->sblk->icptcode != ICPT_VALIDITY) 36d75fac5fSJanosch Frank return; 37d75fac5fSJanosch Frank 38d75fac5fSJanosch Frank vir = vm->sblk->ipb >> 16; 39d75fac5fSJanosch Frank 40d75fac5fSJanosch Frank if (!validity_expected) 41d75fac5fSJanosch Frank report_abort("VALIDITY: %x", vir); 42d75fac5fSJanosch Frank validity_expected = false; 43d75fac5fSJanosch Frank } 44a58e5546SJanosch Frank 45*ab68f968SJanosch Frank void sie(struct vm *vm) 46*ab68f968SJanosch Frank { 47*ab68f968SJanosch Frank /* Reset icptcode so we don't trip over it below */ 48*ab68f968SJanosch Frank vm->sblk->icptcode = 0; 49*ab68f968SJanosch Frank 50*ab68f968SJanosch Frank while (vm->sblk->icptcode == 0) { 51*ab68f968SJanosch Frank sie64a(vm->sblk, &vm->save_area); 52*ab68f968SJanosch Frank sie_handle_validity(vm); 53*ab68f968SJanosch Frank } 54*ab68f968SJanosch Frank vm->save_area.guest.grs[14] = vm->sblk->gg14; 55*ab68f968SJanosch Frank vm->save_area.guest.grs[15] = vm->sblk->gg15; 56*ab68f968SJanosch Frank } 57*ab68f968SJanosch Frank 58a58e5546SJanosch Frank /* Initializes the struct vm members like the SIE control block. */ 59a58e5546SJanosch Frank void sie_guest_create(struct vm *vm, uint64_t guest_mem, uint64_t guest_mem_len) 60a58e5546SJanosch Frank { 61a58e5546SJanosch Frank vm->sblk = alloc_page(); 62a58e5546SJanosch Frank memset(vm->sblk, 0, PAGE_SIZE); 63a58e5546SJanosch Frank vm->sblk->cpuflags = CPUSTAT_ZARCH | CPUSTAT_RUNNING; 64a58e5546SJanosch Frank vm->sblk->ihcpu = 0xffff; 65a58e5546SJanosch Frank vm->sblk->prefix = 0; 66a58e5546SJanosch Frank 67a58e5546SJanosch Frank /* Guest memory chunks are always 1MB */ 68a58e5546SJanosch Frank assert(!(guest_mem_len & ~HPAGE_MASK)); 69a58e5546SJanosch Frank /* Currently MSO/MSL is the easiest option */ 70a58e5546SJanosch Frank vm->sblk->mso = (uint64_t)guest_mem; 71a58e5546SJanosch Frank vm->sblk->msl = (uint64_t)guest_mem + ((guest_mem_len - 1) & HPAGE_MASK); 72a58e5546SJanosch Frank 73a58e5546SJanosch Frank /* CRYCB needs to be in the first 2GB */ 74a58e5546SJanosch Frank vm->crycb = alloc_pages_flags(0, AREA_DMA31); 75a58e5546SJanosch Frank vm->sblk->crycbd = (uint32_t)(uintptr_t)vm->crycb; 76a58e5546SJanosch Frank } 77a58e5546SJanosch Frank 78a58e5546SJanosch Frank /* Frees the memory that was gathered on initialization */ 79a58e5546SJanosch Frank void sie_guest_destroy(struct vm *vm) 80a58e5546SJanosch Frank { 81a58e5546SJanosch Frank free_page(vm->crycb); 82a58e5546SJanosch Frank free_page(vm->sblk); 83a58e5546SJanosch Frank } 84