1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2024 Ruslan Bukin <br@bsdpad.com> 5 * 6 * This software was developed by the University of Cambridge Computer 7 * Laboratory (Department of Computer Science and Technology) under Innovate 8 * UK project 105694, "Digital Security by Design (DSbD) Technology Platform 9 * Prototype". 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/kernel.h> 35 #include <sys/jail.h> 36 #include <sys/queue.h> 37 #include <sys/lock.h> 38 #include <sys/mutex.h> 39 #include <sys/malloc.h> 40 #include <sys/conf.h> 41 #include <sys/sysctl.h> 42 #include <sys/libkern.h> 43 #include <sys/ioccom.h> 44 #include <sys/mman.h> 45 #include <sys/uio.h> 46 #include <sys/proc.h> 47 48 #include <vm/vm.h> 49 #include <vm/pmap.h> 50 #include <vm/vm_map.h> 51 #include <vm/vm_object.h> 52 53 #include <machine/machdep.h> 54 #include <machine/vmparam.h> 55 #include <machine/vmm.h> 56 #include <machine/vmm_dev.h> 57 #include <machine/md_var.h> 58 #include <machine/sbi.h> 59 60 #include "riscv.h" 61 62 static int 63 vmm_sbi_handle_rfnc(struct vcpu *vcpu, struct hypctx *hypctx) 64 { 65 uint64_t hart_mask __unused; 66 uint64_t start __unused; 67 uint64_t size __unused; 68 uint64_t asid __unused; 69 uint64_t func_id; 70 71 func_id = hypctx->guest_regs.hyp_a[6]; 72 hart_mask = hypctx->guest_regs.hyp_a[0]; 73 start = hypctx->guest_regs.hyp_a[2]; 74 size = hypctx->guest_regs.hyp_a[3]; 75 asid = hypctx->guest_regs.hyp_a[4]; 76 77 dprintf("%s: %ld hart_mask %lx start %lx size %lx\n", __func__, 78 func_id, hart_mask, start, size); 79 80 /* TODO: implement remote sfence. */ 81 82 switch (func_id) { 83 case SBI_RFNC_REMOTE_FENCE_I: 84 break; 85 case SBI_RFNC_REMOTE_SFENCE_VMA: 86 break; 87 case SBI_RFNC_REMOTE_SFENCE_VMA_ASID: 88 break; 89 default: 90 break; 91 } 92 93 hypctx->guest_regs.hyp_a[0] = 0; 94 95 return (0); 96 } 97 98 static int 99 vmm_sbi_handle_ipi(struct vcpu *vcpu, struct hypctx *hypctx) 100 { 101 struct hypctx *target_hypctx; 102 struct vcpu *target_vcpu __unused; 103 cpuset_t active_cpus; 104 struct hyp *hyp; 105 uint64_t hart_mask; 106 uint64_t func_id; 107 int hart_id; 108 int bit; 109 int ret; 110 111 func_id = hypctx->guest_regs.hyp_a[6]; 112 hart_mask = hypctx->guest_regs.hyp_a[0]; 113 114 dprintf("%s: hart_mask %lx\n", __func__, hart_mask); 115 116 hyp = hypctx->hyp; 117 118 active_cpus = vm_active_cpus(hyp->vm); 119 120 switch (func_id) { 121 case SBI_IPI_SEND_IPI: 122 while ((bit = ffs(hart_mask))) { 123 hart_id = (bit - 1); 124 hart_mask &= ~(1u << hart_id); 125 if (CPU_ISSET(hart_id, &active_cpus)) { 126 /* TODO. */ 127 target_vcpu = vm_vcpu(hyp->vm, hart_id); 128 target_hypctx = hypctx->hyp->ctx[hart_id]; 129 riscv_send_ipi(target_hypctx, hart_id); 130 } 131 } 132 ret = 0; 133 break; 134 default: 135 printf("%s: unknown func %ld\n", __func__, func_id); 136 ret = -1; 137 break; 138 } 139 140 hypctx->guest_regs.hyp_a[0] = ret; 141 142 return (0); 143 } 144 145 int 146 vmm_sbi_ecall(struct vcpu *vcpu, bool *retu) 147 { 148 int sbi_extension_id __unused; 149 struct hypctx *hypctx; 150 151 hypctx = riscv_get_active_vcpu(); 152 sbi_extension_id = hypctx->guest_regs.hyp_a[7]; 153 154 dprintf("%s: args %lx %lx %lx %lx %lx %lx %lx %lx\n", __func__, 155 hypctx->guest_regs.hyp_a[0], 156 hypctx->guest_regs.hyp_a[1], 157 hypctx->guest_regs.hyp_a[2], 158 hypctx->guest_regs.hyp_a[3], 159 hypctx->guest_regs.hyp_a[4], 160 hypctx->guest_regs.hyp_a[5], 161 hypctx->guest_regs.hyp_a[6], 162 hypctx->guest_regs.hyp_a[7]); 163 164 switch (sbi_extension_id) { 165 case SBI_EXT_ID_RFNC: 166 vmm_sbi_handle_rfnc(vcpu, hypctx); 167 break; 168 case SBI_EXT_ID_TIME: 169 break; 170 case SBI_EXT_ID_IPI: 171 vmm_sbi_handle_ipi(vcpu, hypctx); 172 break; 173 default: 174 *retu = true; 175 break; 176 } 177 178 return (0); 179 } 180