mirror of
https://github.com/torvalds/linux.git
synced 2026-06-02 03:24:19 +02:00
KVM: arm64: Introduce generic get_user/set_user helpers for system registers
The userspace access to the system registers is done using helpers that hardcode the table that is looked up. extract some generic helpers from this, moving the handling of hidden sysregs into the core code. Reviewed-by: Reiji Watanabe <reijiw@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
parent
1deeffb559
commit
ba23aec9f4
|
|
@ -2663,8 +2663,10 @@ const struct sys_reg_desc *get_reg_by_id(u64 id,
|
|||
}
|
||||
|
||||
/* Decode an index value, and find the sys_reg_desc entry. */
|
||||
static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
|
||||
u64 id)
|
||||
static const struct sys_reg_desc *
|
||||
id_to_sys_reg_desc(struct kvm_vcpu *vcpu, u64 id,
|
||||
const struct sys_reg_desc table[], unsigned int num)
|
||||
|
||||
{
|
||||
const struct sys_reg_desc *r;
|
||||
|
||||
|
|
@ -2672,10 +2674,10 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
|
|||
if ((id & KVM_REG_ARM_COPROC_MASK) != KVM_REG_ARM64_SYSREG)
|
||||
return NULL;
|
||||
|
||||
r = get_reg_by_id(id, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
|
||||
r = get_reg_by_id(id, table, num);
|
||||
|
||||
/* Not saved in the sys_reg array and not otherwise accessible? */
|
||||
if (r && !(r->reg || r->get_user))
|
||||
if (r && (!(r->reg || r->get_user) || sysreg_hidden(vcpu, r)))
|
||||
r = NULL;
|
||||
|
||||
return r;
|
||||
|
|
@ -2845,9 +2847,24 @@ static int demux_c15_set(u64 id, void __user *uaddr)
|
|||
}
|
||||
}
|
||||
|
||||
int kvm_sys_reg_get_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
const struct sys_reg_desc table[], unsigned int num)
|
||||
{
|
||||
void __user *uaddr = (void __user *)(unsigned long)reg->addr;
|
||||
const struct sys_reg_desc *r;
|
||||
|
||||
r = id_to_sys_reg_desc(vcpu, reg->id, table, num);
|
||||
if (!r)
|
||||
return -ENOENT;
|
||||
|
||||
if (r->get_user)
|
||||
return (r->get_user)(vcpu, r, reg, uaddr);
|
||||
|
||||
return reg_to_user(uaddr, &__vcpu_sys_reg(vcpu, r->reg), reg->id);
|
||||
}
|
||||
|
||||
int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
{
|
||||
const struct sys_reg_desc *r;
|
||||
void __user *uaddr = (void __user *)(unsigned long)reg->addr;
|
||||
int err;
|
||||
|
||||
|
|
@ -2861,21 +2878,28 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
|
|||
if (err != -ENOENT)
|
||||
return err;
|
||||
|
||||
r = index_to_sys_reg_desc(vcpu, reg->id);
|
||||
return kvm_sys_reg_get_user(vcpu, reg,
|
||||
sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
|
||||
}
|
||||
|
||||
/* Check for regs disabled by runtime config */
|
||||
if (!r || sysreg_hidden(vcpu, r))
|
||||
int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
const struct sys_reg_desc table[], unsigned int num)
|
||||
{
|
||||
void __user *uaddr = (void __user *)(unsigned long)reg->addr;
|
||||
const struct sys_reg_desc *r;
|
||||
|
||||
r = id_to_sys_reg_desc(vcpu, reg->id, table, num);
|
||||
if (!r)
|
||||
return -ENOENT;
|
||||
|
||||
if (r->get_user)
|
||||
return (r->get_user)(vcpu, r, reg, uaddr);
|
||||
if (r->set_user)
|
||||
return (r->set_user)(vcpu, r, reg, uaddr);
|
||||
|
||||
return reg_to_user(uaddr, &__vcpu_sys_reg(vcpu, r->reg), reg->id);
|
||||
return reg_from_user(&__vcpu_sys_reg(vcpu, r->reg), uaddr, reg->id);
|
||||
}
|
||||
|
||||
int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
|
||||
{
|
||||
const struct sys_reg_desc *r;
|
||||
void __user *uaddr = (void __user *)(unsigned long)reg->addr;
|
||||
int err;
|
||||
|
||||
|
|
@ -2889,16 +2913,8 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg
|
|||
if (err != -ENOENT)
|
||||
return err;
|
||||
|
||||
r = index_to_sys_reg_desc(vcpu, reg->id);
|
||||
|
||||
/* Check for regs disabled by runtime config */
|
||||
if (!r || sysreg_hidden(vcpu, r))
|
||||
return -ENOENT;
|
||||
|
||||
if (r->set_user)
|
||||
return (r->set_user)(vcpu, r, reg, uaddr);
|
||||
|
||||
return reg_from_user(&__vcpu_sys_reg(vcpu, r->reg), uaddr, reg->id);
|
||||
return kvm_sys_reg_set_user(vcpu, reg,
|
||||
sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
|
||||
}
|
||||
|
||||
static unsigned int num_demux_regs(void)
|
||||
|
|
|
|||
|
|
@ -199,6 +199,12 @@ const struct sys_reg_desc *get_reg_by_id(u64 id,
|
|||
const struct sys_reg_desc table[],
|
||||
unsigned int num);
|
||||
|
||||
int kvm_sys_reg_get_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
const struct sys_reg_desc table[], unsigned int num);
|
||||
|
||||
int kvm_sys_reg_set_user(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg,
|
||||
const struct sys_reg_desc table[], unsigned int num);
|
||||
|
||||
#define AA32(_x) .aarch32_map = AA32_##_x
|
||||
#define Op0(_x) .Op0 = _x
|
||||
#define Op1(_x) .Op1 = _x
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user