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 const struct uv_cb_qui *uv_get_query_data(void) 51 { 52 /* Query needs to be called first */ 53 assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100); 54 55 return &uvcb_qui; 56 } 57 58 int uv_setup(void) 59 { 60 if (!test_facility(158)) 61 return 0; 62 63 uv_call(0, (u64)&uvcb_qui); 64 65 assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100); 66 return 1; 67 } 68 69 void uv_init(void) 70 { 71 struct uv_cb_init uvcb_init = { 72 .header.len = sizeof(uvcb_init), 73 .header.cmd = UVC_CMD_INIT_UV, 74 }; 75 static bool initialized; 76 int cc; 77 78 /* Let's not do this twice */ 79 assert(!initialized); 80 /* Query is done on initialization but let's check anyway */ 81 assert(uvcb_qui.header.rc == 1 || uvcb_qui.header.rc == 0x100); 82 83 /* Donated storage needs to be over 2GB aligned to 1MB */ 84 uv_init_mem = (uint64_t)memalign_pages_flags(HPAGE_SIZE, uvcb_qui.uv_base_stor_len, AREA_NORMAL); 85 uvcb_init.stor_origin = uv_init_mem; 86 uvcb_init.stor_len = uvcb_qui.uv_base_stor_len; 87 88 cc = uv_call(0, (uint64_t)&uvcb_init); 89 assert(cc == 0); 90 initialized = true; 91 } 92 93 /* 94 * Create a new ASCE for the UV config because they can't be shared 95 * for security reasons. We just simply copy the top most table into a 96 * fresh set of allocated pages and use those pages as the asce. 97 */ 98 static uint64_t create_asce(void) 99 { 100 void *pgd_new, *pgd_old; 101 uint64_t asce = stctg(1); 102 103 pgd_new = memalign_pages(PAGE_SIZE, PAGE_SIZE * 4); 104 pgd_old = (void *)(asce & PAGE_MASK); 105 106 memcpy(pgd_new, pgd_old, PAGE_SIZE * 4); 107 108 asce = __pa(pgd_new) | ASCE_P | (asce & (ASCE_DT | ASCE_TL)); 109 return asce; 110 } 111 112 void uv_create_guest(struct vm *vm) 113 { 114 struct uv_cb_cgc uvcb_cgc = { 115 .header.cmd = UVC_CMD_CREATE_SEC_CONF, 116 .header.len = sizeof(uvcb_cgc), 117 }; 118 struct uv_cb_csc uvcb_csc = { 119 .header.len = sizeof(uvcb_csc), 120 .header.cmd = UVC_CMD_CREATE_SEC_CPU, 121 .state_origin = (uint64_t)vm->sblk, 122 .num = 0, 123 }; 124 unsigned long vsize; 125 int cc; 126 127 uvcb_cgc.guest_stor_origin = vm->sblk->mso; 128 uvcb_cgc.guest_stor_len = vm->sblk->msl; 129 130 /* Config allocation */ 131 vsize = uvcb_qui.conf_base_virt_stor_len + 132 ((uvcb_cgc.guest_stor_len / HPAGE_SIZE) * uvcb_qui.conf_virt_var_stor_len); 133 134 vm->uv.conf_base_stor = memalign_pages_flags(PAGE_SIZE * 4, uvcb_qui.conf_base_phys_stor_len, 0); 135 /* 136 * This allocation needs to be below the max guest storage 137 * address so let's simply put it into the physical memory 138 */ 139 vm->uv.conf_var_stor = memalign_pages_flags(PAGE_SIZE, vsize,0); 140 uvcb_cgc.conf_base_stor_origin = (uint64_t)vm->uv.conf_base_stor; 141 uvcb_cgc.conf_var_stor_origin = (uint64_t)vm->uv.conf_var_stor; 142 143 /* CPU allocation */ 144 vm->uv.cpu_stor = memalign_pages_flags(PAGE_SIZE, uvcb_qui.cpu_stor_len, 0); 145 uvcb_csc.stor_origin = (uint64_t)vm->uv.cpu_stor; 146 147 uvcb_cgc.guest_asce = create_asce(); 148 vm->save_area.guest.asce = uvcb_cgc.guest_asce; 149 uvcb_cgc.guest_sca = (uint64_t)vm->sca; 150 151 cc = uv_call(0, (uint64_t)&uvcb_cgc); 152 assert(!cc); 153 154 vm->uv.vm_handle = uvcb_cgc.guest_handle; 155 uvcb_csc.guest_handle = uvcb_cgc.guest_handle; 156 cc = uv_call(0, (uint64_t)&uvcb_csc); 157 vm->uv.vcpu_handle = uvcb_csc.cpu_handle; 158 assert(!cc); 159 160 /* 161 * Convert guest to format 4: 162 * 163 * - Set format 4 164 * - Write UV handles into sblk 165 * - Allocate and set SIDA 166 */ 167 vm->sblk->sdf = 2; 168 vm->sblk->sidad = (uint64_t)alloc_page(); 169 vm->sblk->pv_handle_cpu = uvcb_csc.cpu_handle; 170 vm->sblk->pv_handle_config = uvcb_cgc.guest_handle; 171 } 172 173 void uv_destroy_guest(struct vm *vm) 174 { 175 int cc; 176 u16 rc, rrc; 177 178 cc = uv_cmd_nodata(vm->sblk->pv_handle_cpu, 179 UVC_CMD_DESTROY_SEC_CPU, &rc, &rrc); 180 assert(cc == 0); 181 free_page((void *)vm->sblk->sidad); 182 free_pages(vm->uv.cpu_stor); 183 184 cc = uv_cmd_nodata(vm->sblk->pv_handle_config, 185 UVC_CMD_DESTROY_SEC_CONF, &rc, &rrc); 186 assert(cc == 0); 187 free_pages(vm->uv.conf_base_stor); 188 free_pages(vm->uv.conf_var_stor); 189 190 free_pages((void *)(vm->uv.asce & PAGE_MASK)); 191 } 192 193 int uv_unpack(struct vm *vm, uint64_t addr, uint64_t len, uint64_t tweak) 194 { 195 int i, cc; 196 197 for (i = 0; i < len / PAGE_SIZE; i++) { 198 cc = uv_unp_page(vm->uv.vm_handle, addr, tweak, i * PAGE_SIZE); 199 assert(!cc); 200 addr += PAGE_SIZE; 201 } 202 return cc; 203 } 204 205 void uv_verify_load(struct vm *vm) 206 { 207 uint16_t rc, rrc; 208 int cc; 209 210 cc = uv_cmd_nodata(vm->uv.vm_handle, UVC_CMD_VERIFY_IMG, &rc, &rrc); 211 assert(!cc); 212 cc = uv_set_cpu_state(vm->uv.vcpu_handle, PV_CPU_STATE_OPR_LOAD); 213 assert(!cc); 214 } 215