Commit db25081e authored by Marc Zyngier's avatar Marc Zyngier

KVM: arm64: vgic-v3: Push user access into vgic_v3_cpu_sysregs_uaccess()

In order to start making the vgic sysreg access from userspace
similar to all the other sysregs, push the userspace memory
access one level down into vgic_v3_cpu_sysregs_uaccess().

The next step will be to rely on the sysreg infrastructure
to perform this task.
Reviewed-by: default avatarReiji Watanabe <reijiw@google.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parent b61fc085
...@@ -278,15 +278,21 @@ int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr * ...@@ -278,15 +278,21 @@ int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *
return -ENXIO; return -ENXIO;
} }
int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id, int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu,
u64 *reg) struct kvm_device_attr *attr,
bool is_write)
{ {
u64 __user *uaddr = (u64 __user *)(long)attr->addr;
struct sys_reg_params params; struct sys_reg_params params;
const struct sys_reg_desc *r; const struct sys_reg_desc *r;
u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64; u64 sysreg;
if (is_write) sysreg = attr_to_id(attr->attr);
params.regval = *reg;
if (is_write) {
if (get_user(params.regval, uaddr))
return -EFAULT;
}
params.is_write = is_write; params.is_write = is_write;
r = find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs, r = find_reg_by_id(sysreg, &params, gic_v3_icc_reg_descs,
...@@ -297,8 +303,10 @@ int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id, ...@@ -297,8 +303,10 @@ int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
if (!r->access(vcpu, &params, r)) if (!r->access(vcpu, &params, r))
return -EINVAL; return -EINVAL;
if (!is_write) if (!is_write) {
*reg = params.regval; if (put_user(params.regval, uaddr))
return -EFAULT;
}
return 0; return 0;
} }
...@@ -512,7 +512,7 @@ int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr, ...@@ -512,7 +512,7 @@ int vgic_v3_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
* *
* @dev: kvm device handle * @dev: kvm device handle
* @attr: kvm device attribute * @attr: kvm device attribute
* @reg: address the value is read or written * @reg: address the value is read or written, NULL for sysregs
* @is_write: true if userspace is writing a register * @is_write: true if userspace is writing a register
*/ */
static int vgic_v3_attr_regs_access(struct kvm_device *dev, static int vgic_v3_attr_regs_access(struct kvm_device *dev,
...@@ -561,14 +561,9 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev, ...@@ -561,14 +561,9 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
if (!is_write) if (!is_write)
*reg = tmp32; *reg = tmp32;
break; break;
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: { case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
u64 regid; ret = vgic_v3_cpu_sysregs_uaccess(vcpu, attr, is_write);
regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
regid, reg);
break; break;
}
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: { case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
unsigned int info, intid; unsigned int info, intid;
...@@ -617,15 +612,8 @@ static int vgic_v3_set_attr(struct kvm_device *dev, ...@@ -617,15 +612,8 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
reg = tmp32; reg = tmp32;
return vgic_v3_attr_regs_access(dev, attr, &reg, true); return vgic_v3_attr_regs_access(dev, attr, &reg, true);
} }
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: { case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
u64 __user *uaddr = (u64 __user *)(long)attr->addr; return vgic_v3_attr_regs_access(dev, attr, NULL, true);
u64 reg;
if (get_user(reg, uaddr))
return -EFAULT;
return vgic_v3_attr_regs_access(dev, attr, &reg, true);
}
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: { case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
u32 __user *uaddr = (u32 __user *)(long)attr->addr; u32 __user *uaddr = (u32 __user *)(long)attr->addr;
u64 reg; u64 reg;
...@@ -681,15 +669,8 @@ static int vgic_v3_get_attr(struct kvm_device *dev, ...@@ -681,15 +669,8 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
tmp32 = reg; tmp32 = reg;
return put_user(tmp32, uaddr); return put_user(tmp32, uaddr);
} }
case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS: { case KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS:
u64 __user *uaddr = (u64 __user *)(long)attr->addr; return vgic_v3_attr_regs_access(dev, attr, NULL, false);
u64 reg;
ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
if (ret)
return ret;
return put_user(reg, uaddr);
}
case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: { case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
u32 __user *uaddr = (u32 __user *)(long)attr->addr; u32 __user *uaddr = (u32 __user *)(long)attr->addr;
u64 reg; u64 reg;
......
...@@ -245,8 +245,8 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write, ...@@ -245,8 +245,8 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
int offset, u32 *val); int offset, u32 *val);
int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write, int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
int offset, u32 *val); int offset, u32 *val);
int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu,
u64 id, u64 *val); struct kvm_device_attr *attr, bool is_write);
int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr);
int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write, int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
u32 intid, u64 *val); u32 intid, u64 *val);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment