1 // SPDX-License-Identifier: GPL-2.0-only 2 #include "kvm_util.h" 3 #include "linux/types.h" 4 #include "linux/bitmap.h" 5 #include "linux/atomic.h" 6 7 #define GUEST_UCALL_FAILED -1 8 9 struct ucall_header { 10 DECLARE_BITMAP(in_use, KVM_MAX_VCPUS); 11 struct ucall ucalls[KVM_MAX_VCPUS]; 12 }; 13 14 /* 15 * ucall_pool holds per-VM values (global data is duplicated by each VM), it 16 * must not be accessed from host code. 17 */ 18 static struct ucall_header *ucall_pool; 19 20 void ucall_init(struct kvm_vm *vm, vm_paddr_t mmio_gpa) 21 { 22 struct ucall_header *hdr; 23 struct ucall *uc; 24 vm_vaddr_t vaddr; 25 int i; 26 27 vaddr = __vm_vaddr_alloc(vm, sizeof(*hdr), KVM_UTIL_MIN_VADDR, MEM_REGION_DATA); 28 hdr = (struct ucall_header *)addr_gva2hva(vm, vaddr); 29 memset(hdr, 0, sizeof(*hdr)); 30 31 for (i = 0; i < KVM_MAX_VCPUS; ++i) { 32 uc = &hdr->ucalls[i]; 33 uc->hva = uc; 34 } 35 36 write_guest_global(vm, ucall_pool, (struct ucall_header *)vaddr); 37 38 ucall_arch_init(vm, mmio_gpa); 39 } 40 41 static struct ucall *ucall_alloc(void) 42 { 43 struct ucall *uc; 44 int i; 45 46 if (!ucall_pool) 47 goto ucall_failed; 48 49 for (i = 0; i < KVM_MAX_VCPUS; ++i) { 50 if (!test_and_set_bit(i, ucall_pool->in_use)) { 51 uc = &ucall_pool->ucalls[i]; 52 memset(uc->args, 0, sizeof(uc->args)); 53 return uc; 54 } 55 } 56 57 ucall_failed: 58 /* 59 * If the vCPU cannot grab a ucall structure, make a bare ucall with a 60 * magic value to signal to get_ucall() that things went sideways. 61 * GUEST_ASSERT() depends on ucall_alloc() and so cannot be used here. 62 */ 63 ucall_arch_do_ucall(GUEST_UCALL_FAILED); 64 return NULL; 65 } 66 67 static void ucall_free(struct ucall *uc) 68 { 69 /* Beware, here be pointer arithmetic. */ 70 clear_bit(uc - ucall_pool->ucalls, ucall_pool->in_use); 71 } 72 73 void ucall(uint64_t cmd, int nargs, ...) 74 { 75 struct ucall *uc; 76 va_list va; 77 int i; 78 79 uc = ucall_alloc(); 80 81 WRITE_ONCE(uc->cmd, cmd); 82 83 nargs = min(nargs, UCALL_MAX_ARGS); 84 85 va_start(va, nargs); 86 for (i = 0; i < nargs; ++i) 87 WRITE_ONCE(uc->args[i], va_arg(va, uint64_t)); 88 va_end(va); 89 90 ucall_arch_do_ucall((vm_vaddr_t)uc->hva); 91 92 ucall_free(uc); 93 } 94 95 uint64_t get_ucall(struct kvm_vcpu *vcpu, struct ucall *uc) 96 { 97 struct ucall ucall; 98 void *addr; 99 100 if (!uc) 101 uc = &ucall; 102 103 addr = ucall_arch_get_ucall(vcpu); 104 if (addr) { 105 TEST_ASSERT(addr != (void *)GUEST_UCALL_FAILED, 106 "Guest failed to allocate ucall struct"); 107 108 memcpy(uc, addr, sizeof(*uc)); 109 vcpu_run_complete_io(vcpu); 110 } else { 111 memset(uc, 0, sizeof(*uc)); 112 } 113 114 return uc->cmd; 115 } 116