提交 c42a0201 编写于 作者: P Peng Liang 提交者: Zheng Zengkai

kvm: arm64: emulate the ID registers

hulk inclusion
category: feature
bugzilla: 48052
CVE: NA

------------------------------

To emulate the ID registers, we need a place to storage the values of
the ID regsiters.  Maybe putting in kvm_arch_vcpu is a good idea.

This commit has no functional changes but only code refactor.  When
initializing a vcpu, get the values of the ID registers from
arm64_ftr_regs and storage them in kvm_arch_vcpu.  And we just read
the value from kvm_arch_vcpu when getting/setting the value of the ID
regs.
Signed-off-by: Nzhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: NPeng Liang <liangpeng10@huawei.com>
Reviewed-by: NZhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 c4695bab
...@@ -387,6 +387,8 @@ struct kvm_vcpu_arch { ...@@ -387,6 +387,8 @@ struct kvm_vcpu_arch {
bool pv_unhalted; bool pv_unhalted;
gpa_t base; gpa_t base;
} pvsched; } pvsched;
struct id_registers idregs;
}; };
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */ /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
......
...@@ -269,6 +269,24 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id) ...@@ -269,6 +269,24 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
return 0; return 0;
} }
static int get_cpu_ftr(u32 id, u64 val, void *argp)
{
struct id_registers *idregs = argp;
/*
* (Op0, Op1, CRn, CRm, Op2) of ID registers is (3, 0, 0, crm, op2),
* where 1<=crm<8, 0<=op2<8.
*/
if (sys_reg_Op0(id) == 3 && sys_reg_Op1(id) == 0 &&
sys_reg_CRn(id) == 0 && sys_reg_CRm(id) > 0) {
idregs->regs[idregs->num].sys_id = id;
idregs->regs[idregs->num].sys_val = val;
idregs->num++;
}
return 0;
}
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{ {
int err; int err;
...@@ -296,6 +314,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) ...@@ -296,6 +314,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
if (err) if (err)
return err; return err;
err = arm64_cpu_ftr_regs_traverse(get_cpu_ftr, &vcpu->arch.idregs);
if (err)
return err;
return create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP); return create_hyp_mappings(vcpu, vcpu + 1, PAGE_HYP);
} }
......
...@@ -1112,13 +1112,35 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu, ...@@ -1112,13 +1112,35 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
return true; return true;
} }
static struct id_reg_info *kvm_id_reg(struct kvm_vcpu *vcpu, u64 id)
{
int i;
for (i = 0; i < vcpu->arch.idregs.num; ++i) {
if (vcpu->arch.idregs.regs[i].sys_id == id)
return &vcpu->arch.idregs.regs[i];
}
return NULL;
}
static u64 kvm_get_id_reg(struct kvm_vcpu *vcpu, u64 id)
{
struct id_reg_info *ri = kvm_id_reg(vcpu, id);
if (!ri) {
WARN_ON(1);
return 0;
}
return ri->sys_val;
}
/* Read a sanitised cpufeature ID register by sys_reg_desc */ /* Read a sanitised cpufeature ID register by sys_reg_desc */
static u64 read_id_reg(const struct kvm_vcpu *vcpu, static u64 read_id_reg(struct kvm_vcpu *vcpu,
struct sys_reg_desc const *r, bool raz) struct sys_reg_desc const *r, bool raz)
{ {
u32 id = sys_reg((u32)r->Op0, (u32)r->Op1, u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
(u32)r->CRn, (u32)r->CRm, (u32)r->Op2); (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
u64 val = raz ? 0 : read_sanitised_ftr_reg(id); u64 val = raz ? 0 : kvm_get_id_reg(vcpu, id);
if (id == SYS_ID_AA64PFR0_EL1) { if (id == SYS_ID_AA64PFR0_EL1) {
if (!vcpu_has_sve(vcpu)) if (!vcpu_has_sve(vcpu))
...@@ -1249,7 +1271,7 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu, ...@@ -1249,7 +1271,7 @@ static int set_id_aa64pfr0_el1(struct kvm_vcpu *vcpu,
* are stored, and for set_id_reg() we don't allow the effective value * are stored, and for set_id_reg() we don't allow the effective value
* to be changed. * to be changed.
*/ */
static int __get_id_reg(const struct kvm_vcpu *vcpu, static int __get_id_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd, void __user *uaddr, const struct sys_reg_desc *rd, void __user *uaddr,
bool raz) bool raz)
{ {
...@@ -1259,7 +1281,7 @@ static int __get_id_reg(const struct kvm_vcpu *vcpu, ...@@ -1259,7 +1281,7 @@ static int __get_id_reg(const struct kvm_vcpu *vcpu,
return reg_to_user(uaddr, &val, id); return reg_to_user(uaddr, &val, id);
} }
static int __set_id_reg(const struct kvm_vcpu *vcpu, static int __set_id_reg(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *rd, void __user *uaddr, const struct sys_reg_desc *rd, void __user *uaddr,
bool raz) bool raz)
{ {
......
...@@ -1298,6 +1298,17 @@ struct kvm_vfio_spapr_tce { ...@@ -1298,6 +1298,17 @@ struct kvm_vfio_spapr_tce {
__s32 tablefd; __s32 tablefd;
}; };
#define ID_REG_MAX_NUMS 64
struct id_reg_info {
__u64 sys_id;
__u64 sys_val;
};
struct id_registers {
struct id_reg_info regs[ID_REG_MAX_NUMS];
__u64 num;
};
/* /*
* ioctls for VM fds * ioctls for VM fds
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册