RISC-V: KVM: Expose APLIC registers as attributes of AIA irqchip
authorAnup Patel <apatel@ventanamicro.com>
Thu, 15 Jun 2023 07:33:51 +0000 (13:03 +0530)
committerAnup Patel <anup@brainfault.org>
Sun, 18 Jun 2023 15:54:50 +0000 (21:24 +0530)
We expose APLIC registers as KVM device attributes of the in-kernel
AIA irqchip device. This will allow KVM user-space to save/restore
APLIC state using KVM device ioctls().

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Atish Patra <atishp@rivosinc.com>
Signed-off-by: Anup Patel <anup@brainfault.org>
arch/riscv/include/asm/kvm_aia.h
arch/riscv/include/uapi/asm/kvm.h
arch/riscv/kvm/aia_aplic.c
arch/riscv/kvm/aia_device.c

index f6bd852..ba939c0 100644 (file)
@@ -129,6 +129,9 @@ static inline void kvm_riscv_vcpu_aia_imsic_cleanup(struct kvm_vcpu *vcpu)
 {
 }
 
+int kvm_riscv_aia_aplic_set_attr(struct kvm *kvm, unsigned long type, u32 v);
+int kvm_riscv_aia_aplic_get_attr(struct kvm *kvm, unsigned long type, u32 *v);
+int kvm_riscv_aia_aplic_has_attr(struct kvm *kvm, unsigned long type);
 int kvm_riscv_aia_aplic_inject(struct kvm *kvm, u32 source, bool level);
 int kvm_riscv_aia_aplic_init(struct kvm *kvm);
 void kvm_riscv_aia_aplic_cleanup(struct kvm *kvm);
index 047c8fc..9ed822f 100644 (file)
@@ -249,6 +249,12 @@ enum KVM_RISCV_SBI_EXT_ID {
 #define KVM_DEV_RISCV_AIA_GRP_CTRL             2
 #define KVM_DEV_RISCV_AIA_CTRL_INIT            0
 
+/*
+ * The device attribute type contains the memory mapped offset of the
+ * APLIC register (range 0x0000-0x3FFF) and it must be 4-byte aligned.
+ */
+#define KVM_DEV_RISCV_AIA_GRP_APLIC            3
+
 /* One single KVM irqchip, ie. the AIA */
 #define KVM_NR_IRQCHIPS                        1
 
index eecd8f4..39e72aa 100644 (file)
@@ -501,6 +501,49 @@ static struct kvm_io_device_ops aplic_iodoev_ops = {
        .write = aplic_mmio_write,
 };
 
+int kvm_riscv_aia_aplic_set_attr(struct kvm *kvm, unsigned long type, u32 v)
+{
+       int rc;
+
+       if (!kvm->arch.aia.aplic_state)
+               return -ENODEV;
+
+       rc = aplic_mmio_write_offset(kvm, type, v);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+int kvm_riscv_aia_aplic_get_attr(struct kvm *kvm, unsigned long type, u32 *v)
+{
+       int rc;
+
+       if (!kvm->arch.aia.aplic_state)
+               return -ENODEV;
+
+       rc = aplic_mmio_read_offset(kvm, type, v);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
+int kvm_riscv_aia_aplic_has_attr(struct kvm *kvm, unsigned long type)
+{
+       int rc;
+       u32 val;
+
+       if (!kvm->arch.aia.aplic_state)
+               return -ENODEV;
+
+       rc = aplic_mmio_read_offset(kvm, type, &val);
+       if (rc)
+               return rc;
+
+       return 0;
+}
+
 int kvm_riscv_aia_aplic_init(struct kvm *kvm)
 {
        int i, ret = 0;
index 7ab5551..c649ad6 100644 (file)
@@ -366,6 +366,15 @@ static int aia_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
                }
 
                break;
+       case KVM_DEV_RISCV_AIA_GRP_APLIC:
+               if (copy_from_user(&nr, uaddr, sizeof(nr)))
+                       return -EFAULT;
+
+               mutex_lock(&dev->kvm->lock);
+               r = kvm_riscv_aia_aplic_set_attr(dev->kvm, type, nr);
+               mutex_unlock(&dev->kvm->lock);
+
+               break;
        }
 
        return r;
@@ -413,6 +422,20 @@ static int aia_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
                        return -EFAULT;
 
                break;
+       case KVM_DEV_RISCV_AIA_GRP_APLIC:
+               if (copy_from_user(&nr, uaddr, sizeof(nr)))
+                       return -EFAULT;
+
+               mutex_lock(&dev->kvm->lock);
+               r = kvm_riscv_aia_aplic_get_attr(dev->kvm, type, &nr);
+               mutex_unlock(&dev->kvm->lock);
+               if (r)
+                       return r;
+
+               if (copy_to_user(uaddr, &nr, sizeof(nr)))
+                       return -EFAULT;
+
+               break;
        }
 
        return r;
@@ -448,6 +471,8 @@ static int aia_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
                        return 0;
                }
                break;
+       case KVM_DEV_RISCV_AIA_GRP_APLIC:
+               return kvm_riscv_aia_aplic_has_attr(dev->kvm, attr->attr);
        }
 
        return -ENXIO;