提交 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 {
bool pv_unhalted;
gpa_t base;
} pvsched;
struct id_registers idregs;
};
/* 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)
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 err;
......@@ -296,6 +314,10 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
if (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);
}
......
......@@ -1112,13 +1112,35 @@ static bool access_arch_timer(struct kvm_vcpu *vcpu,
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 */
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)
{
u32 id = sys_reg((u32)r->Op0, (u32)r->Op1,
(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 (!vcpu_has_sve(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
* 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,
bool raz)
{
......@@ -1259,7 +1281,7 @@ static int __get_id_reg(const struct kvm_vcpu *vcpu,
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,
bool raz)
{
......
......@@ -1298,6 +1298,17 @@ struct kvm_vfio_spapr_tce {
__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
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册