[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creating
From: |
Shannon Zhao |
Subject: |
[Qemu-arm] [PATCH RFC 3/7] ARM64: KVM: Reset ID registers when creating the VCPUs |
Date: |
Mon, 16 Jan 2017 17:33:30 +0800 |
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.
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);
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);
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]);
+}
--
2.0.4
- [Qemu-arm] [PATCH RFC 4/7] ARM64: KVM: emulate accessing ID registers, (continued)
- [Qemu-arm] [PATCH RFC 4/7] ARM64: KVM: emulate accessing ID registers, Shannon Zhao, 2017/01/16
- [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 <=