1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Library for managing various aspects of guests 4 * 5 * Copyright (c) 2021 IBM Corp 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.ibm.com> 9 */ 10 11 #include <asm/barrier.h> 12 #include <libcflat.h> 13 #include <sie.h> 14 #include <asm/page.h> 15 #include <libcflat.h> 16 #include <alloc_page.h> 17 18 static bool validity_expected; 19 static uint16_t vir; /* Validity interception reason */ 20 21 void sie_expect_validity(void) 22 { 23 validity_expected = true; 24 vir = 0; 25 } 26 27 void sie_check_validity(uint16_t vir_exp) 28 { 29 report(vir_exp == vir, "VALIDITY: %x", vir); 30 vir = 0; 31 } 32 33 void sie_handle_validity(struct vm *vm) 34 { 35 if (vm->sblk->icptcode != ICPT_VALIDITY) 36 return; 37 38 vir = vm->sblk->ipb >> 16; 39 40 if (!validity_expected) 41 report_abort("VALIDITY: %x", vir); 42 validity_expected = false; 43 } 44 45 void sie(struct vm *vm) 46 { 47 if (vm->sblk->sdf == 2) 48 memcpy(vm->sblk->pv_grregs, vm->save_area.guest.grs, 49 sizeof(vm->save_area.guest.grs)); 50 51 /* Reset icptcode so we don't trip over it below */ 52 vm->sblk->icptcode = 0; 53 54 while (vm->sblk->icptcode == 0) { 55 sie64a(vm->sblk, &vm->save_area); 56 sie_handle_validity(vm); 57 } 58 vm->save_area.guest.grs[14] = vm->sblk->gg14; 59 vm->save_area.guest.grs[15] = vm->sblk->gg15; 60 61 if (vm->sblk->sdf == 2) 62 memcpy(vm->save_area.guest.grs, vm->sblk->pv_grregs, 63 sizeof(vm->save_area.guest.grs)); 64 } 65 66 void sie_guest_sca_create(struct vm *vm) 67 { 68 vm->sca = (struct esca_block *)alloc_page(); 69 70 /* Let's start out with one page of ESCA for now */ 71 vm->sblk->scaoh = ((uint64_t)vm->sca >> 32); 72 vm->sblk->scaol = (uint64_t)vm->sca & ~0x3fU; 73 vm->sblk->ecb2 |= ECB2_ESCA; 74 } 75 76 /* Initializes the struct vm members like the SIE control block. */ 77 void sie_guest_create(struct vm *vm, uint64_t guest_mem, uint64_t guest_mem_len) 78 { 79 vm->sblk = alloc_page(); 80 memset(vm->sblk, 0, PAGE_SIZE); 81 vm->sblk->cpuflags = CPUSTAT_ZARCH | CPUSTAT_RUNNING; 82 vm->sblk->ihcpu = 0xffff; 83 vm->sblk->prefix = 0; 84 85 /* Guest memory chunks are always 1MB */ 86 assert(!(guest_mem_len & ~HPAGE_MASK)); 87 /* Currently MSO/MSL is the easiest option */ 88 vm->sblk->mso = (uint64_t)guest_mem; 89 vm->sblk->msl = (uint64_t)guest_mem + ((guest_mem_len - 1) & HPAGE_MASK); 90 91 /* CRYCB needs to be in the first 2GB */ 92 vm->crycb = alloc_pages_flags(0, AREA_DMA31); 93 vm->sblk->crycbd = (uint32_t)(uintptr_t)vm->crycb; 94 } 95 96 /* Frees the memory that was gathered on initialization */ 97 void sie_guest_destroy(struct vm *vm) 98 { 99 free_page(vm->crycb); 100 free_page(vm->sblk); 101 if (vm->sblk->ecb2 & ECB2_ESCA) 102 free_page(vm->sca); 103 } 104