[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creat
From: |
Andrew Jones |
Subject: |
Re: [Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creating the VCPUs |
Date: |
Sat, 28 Jan 2017 14:32:47 +0100 |
User-agent: |
Mutt/1.6.0.1 (2016-04-01) |
On Mon, Jan 16, 2017 at 05:33:30PM +0800, Shannon Zhao wrote:
> From: Shannon Zhao <address@hidden>
>
> Reset ID registers when creating the VCPUs and store the values per
> VCPU. Also modify the get_invariant_sys_reg and set_invariant_sys_reg
> to get/set the ID register from vcpu context.
The patch does more than that. It also prepares the table to be
used with get/set_one_reg. The name 'invariant' is less and less
fitting, and should probably be changed before this patch
to 'id', or we should just integrate these ID registers into
the sys_reg table. I still haven't seen the motivation for
not doing that yet.
>
> Signed-off-by: Shannon Zhao <address@hidden>
> ---
> arch/arm64/include/asm/kvm_coproc.h | 1 +
> arch/arm64/kvm/guest.c | 1 +
> arch/arm64/kvm/sys_regs.c | 58
> ++++++++++++++++++-------------------
> 3 files changed, 31 insertions(+), 29 deletions(-)
>
> diff --git a/arch/arm64/include/asm/kvm_coproc.h
> b/arch/arm64/include/asm/kvm_coproc.h
> index 0b52377..0801b66 100644
> --- a/arch/arm64/include/asm/kvm_coproc.h
> +++ b/arch/arm64/include/asm/kvm_coproc.h
> @@ -24,6 +24,7 @@
> #include <linux/kvm_host.h>
>
> void kvm_reset_sys_regs(struct kvm_vcpu *vcpu);
> +void kvm_reset_id_sys_regs(struct kvm_vcpu *vcpu);
>
> struct kvm_sys_reg_table {
> const struct sys_reg_desc *table;
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index b37446a..92abe2b 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -48,6 +48,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
>
> int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
> {
> + kvm_reset_id_sys_regs(vcpu);
This call should go in kvm_reset_vcpu
> return 0;
> }
>
> diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
> index bf71eb4..7c5fa03 100644
> --- a/arch/arm64/kvm/sys_regs.c
> +++ b/arch/arm64/kvm/sys_regs.c
> @@ -1440,11 +1440,11 @@ static const struct sys_reg_desc cp15_64_regs[] = {
> * the guest, or a future kvm may trap them.
> */
>
> -#define FUNCTION_INVARIANT(reg)
> \
> - static void get_##reg(struct kvm_vcpu *v, \
> - const struct sys_reg_desc *r) \
> +#define FUNCTION_INVARIANT(register) \
> + static void get_##register(struct kvm_vcpu *v, \
> + const struct sys_reg_desc *r) \
> { \
> - ((struct sys_reg_desc *)r)->val = read_sysreg(reg); \
> + vcpu_id_sys_reg(v, r->reg) = read_sysreg(register); \
> }
>
> FUNCTION_INVARIANT(midr_el1)
> @@ -1480,7 +1480,6 @@ FUNCTION_INVARIANT(id_aa64mmfr1_el1)
> FUNCTION_INVARIANT(clidr_el1)
> FUNCTION_INVARIANT(aidr_el1)
>
> -/* ->val is filled in by kvm_sys_reg_table_init() */
> static struct sys_reg_desc invariant_sys_regs[] = {
> { Op0(0b11), Op1(0b000), CRn(0b0000), CRm(0b0000), Op2(0b000),
> NULL, get_midr_el1, MIDR_EL1 },
> @@ -1952,43 +1951,43 @@ static int reg_to_user(void __user *uaddr, const u64
> *val, u64 id)
> return 0;
> }
>
> -static int get_invariant_sys_reg(u64 id, void __user *uaddr)
> +static int get_invariant_sys_reg(struct kvm_vcpu *vcpu,
> + const struct kvm_one_reg *reg)
> {
> struct sys_reg_params params;
> const struct sys_reg_desc *r;
> + void __user *uaddr = (void __user *)(unsigned long)reg->addr;
>
> - if (!index_to_params(id, ¶ms))
> + if (!index_to_params(reg->id, ¶ms))
> return -ENOENT;
>
> r = find_reg(¶ms, invariant_sys_regs,
> ARRAY_SIZE(invariant_sys_regs));
> if (!r)
> return -ENOENT;
>
> - return reg_to_user(uaddr, &r->val, id);
> + if (r->get_user)
> + return (r->get_user)(vcpu, r, reg, uaddr);
> +
> + return reg_to_user(uaddr, &vcpu_id_sys_reg(vcpu, r->reg), reg->id);
> }
>
> -static int set_invariant_sys_reg(u64 id, void __user *uaddr)
> +static int set_invariant_sys_reg(struct kvm_vcpu *vcpu,
> + const struct kvm_one_reg *reg)
> {
> struct sys_reg_params params;
> const struct sys_reg_desc *r;
> - int err;
> - u64 val = 0; /* Make sure high bits are 0 for 32-bit regs */
> + void __user *uaddr = (void __user *)(unsigned long)reg->addr;
>
> - if (!index_to_params(id, ¶ms))
> + if (!index_to_params(reg->id, ¶ms))
> return -ENOENT;
> r = find_reg(¶ms, invariant_sys_regs,
> ARRAY_SIZE(invariant_sys_regs));
> if (!r)
> return -ENOENT;
>
> - err = reg_from_user(&val, uaddr, id);
> - if (err)
> - return err;
> -
> - /* This is what we mean by invariant: you can't change it. */
> - if (r->val != val)
> - return -EINVAL;
> + if (r->set_user)
> + return (r->set_user)(vcpu, r, reg, uaddr);
>
> - return 0;
> + return reg_from_user(&vcpu_id_sys_reg(vcpu, r->reg), uaddr, reg->id);
> }
>
> static bool is_valid_cache(u32 val)
> @@ -2086,7 +2085,7 @@ int kvm_arm_sys_reg_get_reg(struct kvm_vcpu *vcpu,
> const struct kvm_one_reg *reg
>
> r = index_to_sys_reg_desc(vcpu, reg->id);
> if (!r)
> - return get_invariant_sys_reg(reg->id, uaddr);
> + return get_invariant_sys_reg(vcpu, reg);
>
> if (r->get_user)
> return (r->get_user)(vcpu, r, reg, uaddr);
> @@ -2107,7 +2106,7 @@ int kvm_arm_sys_reg_set_reg(struct kvm_vcpu *vcpu,
> const struct kvm_one_reg *reg
>
> r = index_to_sys_reg_desc(vcpu, reg->id);
> if (!r)
> - return set_invariant_sys_reg(reg->id, uaddr);
> + return set_invariant_sys_reg(vcpu, reg);
>
> if (r->set_user)
> return (r->set_user)(vcpu, r, reg, uaddr);
> @@ -2252,7 +2251,6 @@ static int check_sysreg_table(const struct sys_reg_desc
> *table, unsigned int n)
> void kvm_sys_reg_table_init(void)
> {
> unsigned int i;
> - struct sys_reg_desc clidr;
>
> /* Make sure tables are unique and in order. */
> BUG_ON(check_sysreg_table(sys_reg_descs, ARRAY_SIZE(sys_reg_descs)));
> @@ -2262,10 +2260,6 @@ void kvm_sys_reg_table_init(void)
> BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs)));
> BUG_ON(check_sysreg_table(invariant_sys_regs,
> ARRAY_SIZE(invariant_sys_regs)));
>
> - /* We abuse the reset function to overwrite the table itself. */
> - for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
> - invariant_sys_regs[i].reset(NULL, &invariant_sys_regs[i]);
> -
> /*
> * CLIDR format is awkward, so clean it up. See ARM B4.1.20:
> *
> @@ -2276,8 +2270,7 @@ void kvm_sys_reg_table_init(void)
> * value of 0b000, the values of Ctype4 to Ctype7 must be
> * ignored.
> */
> - get_clidr_el1(NULL, &clidr); /* Ugly... */
> - cache_levels = clidr.val;
> + cache_levels = read_sysreg(clidr_el1);
Hmm... I think this ugly code was here to ensure cache_levels was
derived from the guest view of clidr_el1. With this series that
may no longer be the case, unless we can and do enforce it. We need
Marc to advise here.
> for (i = 0; i < 7; i++)
> if (((cache_levels >> (i*3)) & 7) == 0)
> break;
> @@ -2310,3 +2303,10 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
> if (vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
> panic("Didn't reset vcpu_sys_reg(%zi)", num);
> }
> +
> +void kvm_reset_id_sys_regs(struct kvm_vcpu *vcpu)
> +{
> + unsigned int i;
> + for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++)
> + invariant_sys_regs[i].reset(vcpu, &invariant_sys_regs[i]);
This function should be dropped and the calls to it replaced with
reset_sys_reg_descs(vcpu, invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs))
or whatever the table gets renamed to, now that it's not invariant. Or
all this just goes away if we move the registers into the sys_reg
table...
> +}
> --
> 2.0.4
>
>
Thanks,
drew
- Re: [Qemu-arm] [PATCH RFC 4/7] ARM64: KVM: emulate accessing ID registers, (continued)
- [Qemu-arm] [PATCH RFC 5/7] ARM64: KVM: Support cross type vCPU, Shannon Zhao, 2017/01/16
- [Qemu-arm] [PATCH RFC 2/7] ARM64: KVM: Add reset handlers for all ID registers, Shannon Zhao, 2017/01/16
- [Qemu-arm] [PATCH RFC 6/7] ARM64: KVM: Support heterogeneous system, Shannon Zhao, 2017/01/16
- [Qemu-arm] [PATCH RFC 1/7] ARM64: KVM: Add the definition of ID registers, Shannon Zhao, 2017/01/16
- [Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creating the VCPUs, Shannon Zhao, 2017/01/16
- Re: [Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creating the VCPUs,
Andrew Jones <=