Commit 289a007b authored by Anup Patel's avatar Anup Patel Committed by Anup Patel
Browse files

RISC-V: KVM: Expose APLIC registers as attributes of AIA irqchip



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: default avatarAnup Patel <apatel@ventanamicro.com>
Reviewed-by: default avatarAtish Patra <atishp@rivosinc.com>
Signed-off-by: default avatarAnup Patel <anup@brainfault.org>
parent 74967aa2
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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);
+6 −0
Original line number Diff line number Diff line
@@ -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

+43 −0
Original line number Diff line number Diff line
@@ -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;
+25 −0
Original line number Diff line number Diff line
@@ -365,6 +365,15 @@ static int aia_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
			break;
		}

		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;
	}

@@ -412,6 +421,20 @@ static int aia_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
		if (copy_to_user(uaddr, &addr, sizeof(addr)))
			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;
	}

@@ -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;