1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Ultravisor related functionality 4 * 5 * Copyright 2020 IBM Corp. 6 * 7 * Authors: 8 * Janosch Frank <frankja@linux.ibm.com> 9 */ 10 #include <libcflat.h> 11 #include <bitops.h> 12 #include <alloc.h> 13 #include <alloc_page.h> 14 #include <asm/page.h> 15 #include <asm/arch_def.h> 16 17 #include <asm/facility.h> 18 #include <asm/uv.h> 19 #include <uv.h> 20 #include <sie.h> 21 22 static struct uv_cb_qui uvcb_qui = { 23 .header.cmd = UVC_CMD_QUI, 24 .header.len = sizeof(uvcb_qui), 25 }; 26 static uint64_t uv_init_mem; 27 28 29 bool uv_os_is_guest(void) 30 { 31 return test_facility(158) && 32 uv_query_test_call(BIT_UVC_CMD_SET_SHARED_ACCESS) && 33 uv_query_test_call(BIT_UVC_CMD_REMOVE_SHARED_ACCESS); 34 } 35 36 bool uv_os_is_host(void) 37 { 38 return test_facility(158) && uv_query_test_call(BIT_UVC_CMD_INIT_UV); 39 } 40 41 bool uv_query_test_call(unsigned int nr) 42 { 43 /* Query needs to be called first */ 44 assert(uvcb_qui.header.rc); 45 assert(nr < BITS_PER_LONG * ARRAY_SIZE(uvcb_qui.inst_calls_list)); 46 47 return test_bit_inv(nr, uvcb_qui.inst_calls_list); 48 } 49 50 int uv_setup(void) 51 { 52 if (!test_facility(158)) 53 return 0; 54 55 uv_call(0, (u64)&uvcb_qui); 56 57 assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100); 58 return 1; 59 } 60 61 void uv_init(void) 62 { 63 struct uv_cb_init uvcb_init = { 64 .header.len = sizeof(uvcb_init), 65 .header.cmd = UVC_CMD_INIT_UV, 66 }; 67 static bool initialized; 68 int cc; 69 70 /* Let's not do this twice */ 71 assert(!initialized); 72 /* Query is done on initialization but let's check anyway */ 73 assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100); 74 75 /* Donated storage needs to be over 2GB aligned to 1MB */ 76 uv_init_mem = (uint64_t)memalign_pages_flags(HPAGE_SIZE, uvcb_qui.uv_base_stor_len, AREA_NORMAL); 77 uvcb_init.stor_origin = uv_init_mem; 78 uvcb_init.stor_len = uvcb_qui.uv_base_stor_len; 79 80 cc = uv_call(0, (uint64_t)&uvcb_init); 81 assert(cc == 0); 82 initialized = true; 83 } 84 85 void uv_create_guest(struct vm *vm) 86 { 87 struct uv_cb_cgc uvcb_cgc = { 88 .header.cmd = UVC_CMD_CREATE_SEC_CONF, 89 .header.len = sizeof(uvcb_cgc), 90 }; 91 struct uv_cb_csc uvcb_csc = { 92 .header.len = sizeof(uvcb_csc), 93 .header.cmd = UVC_CMD_CREATE_SEC_CPU, 94 .state_origin = (uint64_t)vm->sblk, 95 .num = 0, 96 }; 97 unsigned long vsize; 98 int cc; 99 100 uvcb_cgc.guest_stor_origin = vm->sblk->mso; 101 uvcb_cgc.guest_stor_len = vm->sblk->msl; 102 103 /* Config allocation */ 104 vsize = uvcb_qui.conf_base_virt_stor_len + 105 ((uvcb_cgc.guest_stor_len / HPAGE_SIZE) * uvcb_qui.conf_virt_var_stor_len); 106 107 vm->uv.conf_base_stor = memalign_pages_flags(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len, 0); 108 /* 109 * This allocation needs to be below the max guest storage 110 * address so let's simply put it into the physical memory 111 */ 112 vm->uv.conf_var_stor = memalign_pages_flags(PAGE_SIZE, vsize,0); 113 uvcb_cgc.conf_base_stor_origin = (uint64_t)vm->uv.conf_base_stor; 114 uvcb_cgc.conf_var_stor_origin = (uint64_t)vm->uv.conf_var_stor; 115 116 /* CPU allocation */ 117 vm->uv.cpu_stor = memalign_pages_flags(PAGE_SIZE, uvcb_qui.cpu_stor_len, 0); 118 uvcb_csc.stor_origin = (uint64_t)vm->uv.cpu_stor; 119 120 uvcb_cgc.guest_asce = (uint64_t)stctg(1); 121 uvcb_cgc.guest_sca = (uint64_t)vm->sca; 122 123 cc = uv_call(0, (uint64_t)&uvcb_cgc); 124 assert(!cc); 125 126 vm->uv.vm_handle = uvcb_cgc.guest_handle; 127 uvcb_csc.guest_handle = uvcb_cgc.guest_handle; 128 cc = uv_call(0, (uint64_t)&uvcb_csc); 129 vm->uv.vcpu_handle = uvcb_csc.cpu_handle; 130 assert(!cc); 131 132 /* 133 * Convert guest to format 4: 134 * 135 * - Set format 4 136 * - Write UV handles into sblk 137 * - Allocate and set SIDA 138 */ 139 vm->sblk->sdf = 2; 140 vm->sblk->sidad = (uint64_t)alloc_page(); 141 vm->sblk->pv_handle_cpu = uvcb_csc.cpu_handle; 142 vm->sblk->pv_handle_config = uvcb_cgc.guest_handle; 143 } 144 145 void uv_destroy_guest(struct vm *vm) 146 { 147 int cc; 148 u16 rc, rrc; 149 150 cc = uv_cmd_nodata(vm->sblk->pv_handle_cpu, 151 UVC_CMD_DESTROY_SEC_CPU, &rc, &rrc); 152 assert(cc == 0); 153 free_page((void *)vm->sblk->sidad); 154 free_pages(vm->uv.cpu_stor); 155 156 cc = uv_cmd_nodata(vm->sblk->pv_handle_config, 157 UVC_CMD_DESTROY_SEC_CONF, &rc, &rrc); 158 assert(cc == 0); 159 free_pages(vm->uv.conf_base_stor); 160 free_pages(vm->uv.conf_var_stor); 161 } 162 163 int uv_unpack(struct vm *vm, uint64_t addr, uint64_t len, uint64_t tweak) 164 { 165 int i, cc; 166 167 for (i = 0; i < len / PAGE_SIZE; i++) { 168 cc = uv_unp_page(vm->uv.vm_handle, addr, tweak, i * PAGE_SIZE); 169 assert(!cc); 170 addr += PAGE_SIZE; 171 } 172 return cc; 173 } 174 175 void uv_verify_load(struct vm *vm) 176 { 177 uint16_t rc, rrc; 178 int cc; 179 180 cc = uv_cmd_nodata(vm->uv.vm_handle, UVC_CMD_VERIFY_IMG, &rc, &rrc); 181 assert(!cc); 182 cc = uv_set_cpu_state(vm->uv.vcpu_handle, PV_CPU_STATE_OPR_LOAD); 183 assert(!cc); 184 } 185