mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 17:59:32 +00:00
KVM: arm64: vgic-v2: Consolidate userspace access for MMIO registers
Align the GICv2 MMIO accesses from userspace with the way the GICv3 code is now structured. Reviewed-by: Reiji Watanabe <reijiw@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
e1246f3f2d
commit
7e9f723c2a
1 changed files with 17 additions and 22 deletions
|
@ -348,17 +348,18 @@ bool lock_all_vcpus(struct kvm *kvm)
|
||||||
*
|
*
|
||||||
* @dev: kvm device handle
|
* @dev: kvm device handle
|
||||||
* @attr: kvm device attribute
|
* @attr: kvm device attribute
|
||||||
* @reg: address the value is read or written
|
|
||||||
* @is_write: true if userspace is writing a register
|
* @is_write: true if userspace is writing a register
|
||||||
*/
|
*/
|
||||||
static int vgic_v2_attr_regs_access(struct kvm_device *dev,
|
static int vgic_v2_attr_regs_access(struct kvm_device *dev,
|
||||||
struct kvm_device_attr *attr,
|
struct kvm_device_attr *attr,
|
||||||
u32 *reg, bool is_write)
|
bool is_write)
|
||||||
{
|
{
|
||||||
|
u32 __user *uaddr = (u32 __user *)(unsigned long)attr->addr;
|
||||||
struct vgic_reg_attr reg_attr;
|
struct vgic_reg_attr reg_attr;
|
||||||
gpa_t addr;
|
gpa_t addr;
|
||||||
struct kvm_vcpu *vcpu;
|
struct kvm_vcpu *vcpu;
|
||||||
int ret;
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
ret = vgic_v2_parse_attr(dev, attr, ®_attr);
|
ret = vgic_v2_parse_attr(dev, attr, ®_attr);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
@ -367,6 +368,10 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
|
||||||
vcpu = reg_attr.vcpu;
|
vcpu = reg_attr.vcpu;
|
||||||
addr = reg_attr.addr;
|
addr = reg_attr.addr;
|
||||||
|
|
||||||
|
if (is_write)
|
||||||
|
if (get_user(val, uaddr))
|
||||||
|
return -EFAULT;
|
||||||
|
|
||||||
mutex_lock(&dev->kvm->lock);
|
mutex_lock(&dev->kvm->lock);
|
||||||
|
|
||||||
ret = vgic_init(dev->kvm);
|
ret = vgic_init(dev->kvm);
|
||||||
|
@ -380,10 +385,10 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
|
||||||
|
|
||||||
switch (attr->group) {
|
switch (attr->group) {
|
||||||
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
|
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
|
||||||
ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, reg);
|
ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, &val);
|
||||||
break;
|
break;
|
||||||
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
||||||
ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, reg);
|
ret = vgic_v2_dist_uaccess(vcpu, is_write, addr, &val);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -393,6 +398,10 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
|
||||||
unlock_all_vcpus(dev->kvm);
|
unlock_all_vcpus(dev->kvm);
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&dev->kvm->lock);
|
mutex_unlock(&dev->kvm->lock);
|
||||||
|
|
||||||
|
if (!ret && !is_write)
|
||||||
|
ret = put_user(val, uaddr);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,15 +416,8 @@ static int vgic_v2_set_attr(struct kvm_device *dev,
|
||||||
|
|
||||||
switch (attr->group) {
|
switch (attr->group) {
|
||||||
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
||||||
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
|
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
|
||||||
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
|
return vgic_v2_attr_regs_access(dev, attr, true);
|
||||||
u32 reg;
|
|
||||||
|
|
||||||
if (get_user(reg, uaddr))
|
|
||||||
return -EFAULT;
|
|
||||||
|
|
||||||
return vgic_v2_attr_regs_access(dev, attr, ®, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
@ -432,15 +434,8 @@ static int vgic_v2_get_attr(struct kvm_device *dev,
|
||||||
|
|
||||||
switch (attr->group) {
|
switch (attr->group) {
|
||||||
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
|
||||||
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
|
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
|
||||||
u32 __user *uaddr = (u32 __user *)(long)attr->addr;
|
return vgic_v2_attr_regs_access(dev, attr, false);
|
||||||
u32 reg = 0;
|
|
||||||
|
|
||||||
ret = vgic_v2_attr_regs_access(dev, attr, ®, false);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
return put_user(reg, uaddr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
|
|
Loading…
Reference in a new issue