Lines Matching +full:hart +full:- +full:index +full:- +full:bits

1 // SPDX-License-Identifier: GPL-2.0
10 #include <linux/bits.h>
11 #include <linux/irqchip/riscv-imsic.h>
19 for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) { in unlock_vcpus()
21 mutex_unlock(&tmp_vcpu->mutex); in unlock_vcpus()
27 unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1); in unlock_all_vcpus()
36 if (!mutex_trylock(&tmp_vcpu->mutex)) { in lock_all_vcpus()
37 unlock_vcpus(kvm, c - 1); in lock_all_vcpus()
49 struct kvm *kvm = dev->kvm; in aia_create()
53 return -EEXIST; in aia_create()
55 ret = -EBUSY; in aia_create()
60 if (vcpu->arch.ran_atleast_once) in aia_create()
65 kvm->arch.aia.in_kernel = true; in aia_create()
80 struct kvm_aia *aia = &kvm->arch.aia; in aia_config()
84 return -EBUSY; in aia_config()
96 * supported on host with non-zero guest in aia_config()
97 * external interrupts (i.e. non-zero in aia_config()
98 * VS-level IMSIC pages). in aia_config()
101 return -EINVAL; in aia_config()
104 return -EINVAL; in aia_config()
106 aia->mode = *nr; in aia_config()
108 *nr = aia->mode; in aia_config()
117 return -EINVAL; in aia_config()
118 aia->nr_ids = *nr; in aia_config()
120 *nr = aia->nr_ids; in aia_config()
126 return -EINVAL; in aia_config()
127 aia->nr_sources = *nr; in aia_config()
129 *nr = aia->nr_sources; in aia_config()
134 return -EINVAL; in aia_config()
135 aia->nr_group_bits = *nr; in aia_config()
137 *nr = aia->nr_group_bits; in aia_config()
143 return -EINVAL; in aia_config()
144 aia->nr_group_shift = *nr; in aia_config()
146 *nr = aia->nr_group_shift; in aia_config()
151 return -EINVAL; in aia_config()
152 aia->nr_hart_bits = *nr; in aia_config()
154 *nr = aia->nr_hart_bits; in aia_config()
159 return -EINVAL; in aia_config()
160 aia->nr_guest_bits = *nr; in aia_config()
162 *nr = aia->nr_guest_bits; in aia_config()
165 return -ENXIO; in aia_config()
173 struct kvm_aia *aia = &kvm->arch.aia; in aia_aplic_addr()
178 return -EBUSY; in aia_aplic_addr()
180 if (*addr & (KVM_DEV_RISCV_APLIC_ALIGN - 1)) in aia_aplic_addr()
181 return -EINVAL; in aia_aplic_addr()
183 aia->aplic_addr = *addr; in aia_aplic_addr()
185 *addr = aia->aplic_addr; in aia_aplic_addr()
198 return -EINVAL; in aia_imsic_addr()
199 vcpu_aia = &vcpu->arch.aia_context; in aia_imsic_addr()
204 return -EBUSY; in aia_imsic_addr()
206 if (*addr & (KVM_DEV_RISCV_IMSIC_ALIGN - 1)) in aia_imsic_addr()
207 return -EINVAL; in aia_imsic_addr()
210 mutex_lock(&vcpu->mutex); in aia_imsic_addr()
212 vcpu_aia->imsic_addr = *addr; in aia_imsic_addr()
214 *addr = vcpu_aia->imsic_addr; in aia_imsic_addr()
215 mutex_unlock(&vcpu->mutex); in aia_imsic_addr()
225 h = aia->nr_hart_bits + aia->nr_guest_bits + in aia_imsic_ppn()
226 IMSIC_MMIO_PAGE_SHIFT - 1; in aia_imsic_ppn()
229 if (aia->nr_group_bits) { in aia_imsic_ppn()
230 h = aia->nr_group_bits + aia->nr_group_shift - 1; in aia_imsic_ppn()
231 l = aia->nr_group_shift; in aia_imsic_ppn()
240 u32 hart = 0, group = 0; in aia_imsic_hart_index() local
242 if (aia->nr_hart_bits) in aia_imsic_hart_index()
243 hart = (addr >> (aia->nr_guest_bits + IMSIC_MMIO_PAGE_SHIFT)) & in aia_imsic_hart_index()
244 GENMASK_ULL(aia->nr_hart_bits - 1, 0); in aia_imsic_hart_index()
245 if (aia->nr_group_bits) in aia_imsic_hart_index()
246 group = (addr >> aia->nr_group_shift) & in aia_imsic_hart_index()
247 GENMASK_ULL(aia->nr_group_bits - 1, 0); in aia_imsic_hart_index()
249 return (group << aia->nr_hart_bits) | hart; in aia_imsic_hart_index()
258 struct kvm_aia *aia = &kvm->arch.aia; in aia_init()
263 return -EBUSY; in aia_init()
266 if (kvm->created_vcpus != atomic_read(&kvm->online_vcpus)) in aia_init()
267 return -EBUSY; in aia_init()
270 if (aia->nr_ids < aia->nr_sources) in aia_init()
271 return -EINVAL; in aia_init()
273 /* APLIC base is required for non-zero number of sources */ in aia_init()
274 if (aia->nr_sources && aia->aplic_addr == KVM_RISCV_AIA_UNDEF_ADDR) in aia_init()
275 return -EINVAL; in aia_init()
284 vaia = &vcpu->arch.aia_context; in aia_init()
287 if (vaia->imsic_addr == KVM_RISCV_AIA_UNDEF_ADDR) { in aia_init()
288 ret = -EINVAL; in aia_init()
294 base_ppn = aia_imsic_ppn(aia, vaia->imsic_addr); in aia_init()
295 if (base_ppn != aia_imsic_ppn(aia, vaia->imsic_addr)) { in aia_init()
296 ret = -EINVAL; in aia_init()
300 /* Update HART index of the IMSIC based on IMSIC base */ in aia_init()
301 vaia->hart_index = aia_imsic_hart_index(aia, in aia_init()
302 vaia->imsic_addr); in aia_init()
311 kvm->arch.aia.initialized = true; in aia_init()
316 for (i = idx - 1; i >= 0; i--) { in aia_init()
330 int nr_vcpus, r = -ENXIO; in aia_set_attr()
331 unsigned long v, type = (unsigned long)attr->attr; in aia_set_attr()
332 void __user *uaddr = (void __user *)(long)attr->addr; in aia_set_attr()
334 switch (attr->group) { in aia_set_attr()
337 return -EFAULT; in aia_set_attr()
339 mutex_lock(&dev->kvm->lock); in aia_set_attr()
340 r = aia_config(dev->kvm, type, &nr, true); in aia_set_attr()
341 mutex_unlock(&dev->kvm->lock); in aia_set_attr()
347 return -EFAULT; in aia_set_attr()
349 nr_vcpus = atomic_read(&dev->kvm->online_vcpus); in aia_set_attr()
350 mutex_lock(&dev->kvm->lock); in aia_set_attr()
352 r = aia_aplic_addr(dev->kvm, &addr, true); in aia_set_attr()
354 r = aia_imsic_addr(dev->kvm, &addr, in aia_set_attr()
355 type - KVM_DEV_RISCV_AIA_ADDR_IMSIC(0), true); in aia_set_attr()
356 mutex_unlock(&dev->kvm->lock); in aia_set_attr()
363 mutex_lock(&dev->kvm->lock); in aia_set_attr()
364 r = aia_init(dev->kvm); in aia_set_attr()
365 mutex_unlock(&dev->kvm->lock); in aia_set_attr()
372 return -EFAULT; in aia_set_attr()
374 mutex_lock(&dev->kvm->lock); in aia_set_attr()
375 r = kvm_riscv_aia_aplic_set_attr(dev->kvm, type, nr); in aia_set_attr()
376 mutex_unlock(&dev->kvm->lock); in aia_set_attr()
381 return -EFAULT; in aia_set_attr()
383 mutex_lock(&dev->kvm->lock); in aia_set_attr()
384 r = kvm_riscv_aia_imsic_rw_attr(dev->kvm, type, true, &v); in aia_set_attr()
385 mutex_unlock(&dev->kvm->lock); in aia_set_attr()
397 int nr_vcpus, r = -ENXIO; in aia_get_attr()
398 void __user *uaddr = (void __user *)(long)attr->addr; in aia_get_attr()
399 unsigned long v, type = (unsigned long)attr->attr; in aia_get_attr()
401 switch (attr->group) { in aia_get_attr()
404 return -EFAULT; in aia_get_attr()
406 mutex_lock(&dev->kvm->lock); in aia_get_attr()
407 r = aia_config(dev->kvm, type, &nr, false); in aia_get_attr()
408 mutex_unlock(&dev->kvm->lock); in aia_get_attr()
413 return -EFAULT; in aia_get_attr()
418 return -EFAULT; in aia_get_attr()
420 nr_vcpus = atomic_read(&dev->kvm->online_vcpus); in aia_get_attr()
421 mutex_lock(&dev->kvm->lock); in aia_get_attr()
423 r = aia_aplic_addr(dev->kvm, &addr, false); in aia_get_attr()
425 r = aia_imsic_addr(dev->kvm, &addr, in aia_get_attr()
426 type - KVM_DEV_RISCV_AIA_ADDR_IMSIC(0), false); in aia_get_attr()
427 mutex_unlock(&dev->kvm->lock); in aia_get_attr()
432 return -EFAULT; in aia_get_attr()
437 return -EFAULT; in aia_get_attr()
439 mutex_lock(&dev->kvm->lock); in aia_get_attr()
440 r = kvm_riscv_aia_aplic_get_attr(dev->kvm, type, &nr); in aia_get_attr()
441 mutex_unlock(&dev->kvm->lock); in aia_get_attr()
446 return -EFAULT; in aia_get_attr()
451 return -EFAULT; in aia_get_attr()
453 mutex_lock(&dev->kvm->lock); in aia_get_attr()
454 r = kvm_riscv_aia_imsic_rw_attr(dev->kvm, type, false, &v); in aia_get_attr()
455 mutex_unlock(&dev->kvm->lock); in aia_get_attr()
460 return -EFAULT; in aia_get_attr()
472 switch (attr->group) { in aia_has_attr()
474 switch (attr->attr) { in aia_has_attr()
486 nr_vcpus = atomic_read(&dev->kvm->online_vcpus); in aia_has_attr()
487 if (attr->attr == KVM_DEV_RISCV_AIA_ADDR_APLIC) in aia_has_attr()
489 else if (attr->attr < KVM_DEV_RISCV_AIA_ADDR_IMSIC(nr_vcpus)) in aia_has_attr()
493 switch (attr->attr) { in aia_has_attr()
499 return kvm_riscv_aia_aplic_has_attr(dev->kvm, attr->attr); in aia_has_attr()
501 return kvm_riscv_aia_imsic_has_attr(dev->kvm, attr->attr); in aia_has_attr()
504 return -ENXIO; in aia_has_attr()
508 .name = "kvm-riscv-aia",
519 if (!kvm_riscv_aia_initialized(vcpu->kvm)) in kvm_riscv_vcpu_aia_update()
528 struct kvm_vcpu_aia_csr *csr = &vcpu->arch.aia_context.guest_csr; in kvm_riscv_vcpu_aia_reset()
530 &vcpu->arch.aia_context.guest_reset_csr; in kvm_riscv_vcpu_aia_reset()
537 if (!kvm_riscv_aia_initialized(vcpu->kvm)) in kvm_riscv_vcpu_aia_reset()
546 struct kvm_vcpu_aia *vaia = &vcpu->arch.aia_context; in kvm_riscv_vcpu_aia_init()
553 * will be done after AIA device is initialized by the user-space. in kvm_riscv_vcpu_aia_init()
559 vaia->imsic_addr = KVM_RISCV_AIA_UNDEF_ADDR; in kvm_riscv_vcpu_aia_init()
560 vaia->hart_index = vcpu->vcpu_idx; in kvm_riscv_vcpu_aia_init()
568 if (!kvm_riscv_aia_initialized(vcpu->kvm)) in kvm_riscv_vcpu_aia_deinit()
583 return -EBUSY; in kvm_riscv_aia_inject_msi_by_id()
587 if (vcpu->arch.aia_context.hart_index == hart_index) in kvm_riscv_aia_inject_msi_by_id()
601 u32 g, toff, iid = msi->data; in kvm_riscv_aia_inject_msi()
602 struct kvm_aia *aia = &kvm->arch.aia; in kvm_riscv_aia_inject_msi()
603 gpa_t target = (((gpa_t)msi->address_hi) << 32) | msi->address_lo; in kvm_riscv_aia_inject_msi()
607 return -EBUSY; in kvm_riscv_aia_inject_msi()
613 g = tppn & (BIT(aia->nr_guest_bits) - 1); in kvm_riscv_aia_inject_msi()
614 tppn &= ~((gpa_t)(BIT(aia->nr_guest_bits) - 1)); in kvm_riscv_aia_inject_msi()
618 ippn = vcpu->arch.aia_context.imsic_addr >> in kvm_riscv_aia_inject_msi()
621 toff = target & (IMSIC_MMIO_PAGE_SZ - 1); in kvm_riscv_aia_inject_msi()
634 return -EBUSY; in kvm_riscv_aia_inject_irq()
642 struct kvm_aia *aia = &kvm->arch.aia; in kvm_riscv_aia_init_vm()
649 * will be done after AIA device is initialized by the user-space. in kvm_riscv_aia_init_vm()
655 aia->mode = (kvm_riscv_aia_nr_hgei) ? in kvm_riscv_aia_init_vm()
657 aia->nr_ids = kvm_riscv_aia_max_ids - 1; in kvm_riscv_aia_init_vm()
658 aia->nr_sources = 0; in kvm_riscv_aia_init_vm()
659 aia->nr_group_bits = 0; in kvm_riscv_aia_init_vm()
660 aia->nr_group_shift = KVM_DEV_RISCV_AIA_GROUP_SHIFT_MIN; in kvm_riscv_aia_init_vm()
661 aia->nr_hart_bits = 0; in kvm_riscv_aia_init_vm()
662 aia->nr_guest_bits = 0; in kvm_riscv_aia_init_vm()
663 aia->aplic_addr = KVM_RISCV_AIA_UNDEF_ADDR; in kvm_riscv_aia_init_vm()