mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 21:57:43 +00:00
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: Reiji Watanabe <reijiw@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
b61fc0857a
commit
db25081e14
3 changed files with 24 additions and 35 deletions
|
@ -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, ¶ms, gic_v3_icc_reg_descs,
|
r = find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
|
||||||
|
@ -297,8 +303,10 @@ int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
|
||||||
if (!r->access(vcpu, ¶ms, r))
|
if (!r->access(vcpu, ¶ms, 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,
|
||||||
*
|
*
|
||||||
* @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,
|
||||||
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,
|
||||||
reg = tmp32;
|
reg = tmp32;
|
||||||
return vgic_v3_attr_regs_access(dev, attr, ®, true);
|
return vgic_v3_attr_regs_access(dev, attr, ®, 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, ®, 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,
|
||||||
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, ®, 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,
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue