Commit dcaffa7b authored by James Morse's avatar James Morse Committed by Marc Zyngier

KVM: arm64: Remove target_table from exit handlers

Whenever KVM searches for a register (e.g. due to a guest exit), it
works with two tables, as the target table overrides the sys_regs array.

Now that everything is in the sys_regs array, and the target table is
empty, stop doing that.

Remove the second table and its size from all the functions that take
it.
Signed-off-by: default avatarJames Morse <james.morse@arm.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200622113317.20477-5-james.morse@arm.com
parent af473829
...@@ -2269,9 +2269,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu, ...@@ -2269,9 +2269,7 @@ static void unhandled_cp_access(struct kvm_vcpu *vcpu,
*/ */
static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *global, const struct sys_reg_desc *global,
size_t nr_global, size_t nr_global)
const struct sys_reg_desc *target_specific,
size_t nr_specific)
{ {
struct sys_reg_params params; struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu); u32 hsr = kvm_vcpu_get_hsr(vcpu);
...@@ -2298,14 +2296,11 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, ...@@ -2298,14 +2296,11 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
} }
/* /*
* Try to emulate the coprocessor access using the target * If the table contains a handler, handle the
* specific table first, and using the global table afterwards.
* If either of the tables contains a handler, handle the
* potential register operation in the case of a read and return * potential register operation in the case of a read and return
* with success. * with success.
*/ */
if (!emulate_cp(vcpu, &params, target_specific, nr_specific) || if (!emulate_cp(vcpu, &params, global, nr_global)) {
!emulate_cp(vcpu, &params, global, nr_global)) {
/* Split up the value between registers for the read side */ /* Split up the value between registers for the read side */
if (!params.is_write) { if (!params.is_write) {
vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval)); vcpu_set_reg(vcpu, Rt, lower_32_bits(params.regval));
...@@ -2326,9 +2321,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu, ...@@ -2326,9 +2321,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
*/ */
static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
const struct sys_reg_desc *global, const struct sys_reg_desc *global,
size_t nr_global, size_t nr_global)
const struct sys_reg_desc *target_specific,
size_t nr_specific)
{ {
struct sys_reg_params params; struct sys_reg_params params;
u32 hsr = kvm_vcpu_get_hsr(vcpu); u32 hsr = kvm_vcpu_get_hsr(vcpu);
...@@ -2344,8 +2337,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, ...@@ -2344,8 +2337,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
params.Op1 = (hsr >> 14) & 0x7; params.Op1 = (hsr >> 14) & 0x7;
params.Op2 = (hsr >> 17) & 0x7; params.Op2 = (hsr >> 17) & 0x7;
if (!emulate_cp(vcpu, &params, target_specific, nr_specific) || if (!emulate_cp(vcpu, &params, global, nr_global)) {
!emulate_cp(vcpu, &params, global, nr_global)) {
if (!params.is_write) if (!params.is_write)
vcpu_set_reg(vcpu, Rt, params.regval); vcpu_set_reg(vcpu, Rt, params.regval);
return 1; return 1;
...@@ -2357,38 +2349,22 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu, ...@@ -2357,38 +2349,22 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
{ {
const struct sys_reg_desc *target_specific; return kvm_handle_cp_64(vcpu, cp15_64_regs, ARRAY_SIZE(cp15_64_regs));
size_t num;
target_specific = get_target_table(vcpu->arch.target, false, &num);
return kvm_handle_cp_64(vcpu,
cp15_64_regs, ARRAY_SIZE(cp15_64_regs),
target_specific, num);
} }
int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
{ {
const struct sys_reg_desc *target_specific; return kvm_handle_cp_32(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
size_t num;
target_specific = get_target_table(vcpu->arch.target, false, &num);
return kvm_handle_cp_32(vcpu,
cp15_regs, ARRAY_SIZE(cp15_regs),
target_specific, num);
} }
int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run) int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
{ {
return kvm_handle_cp_64(vcpu, return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs));
cp14_64_regs, ARRAY_SIZE(cp14_64_regs),
NULL, 0);
} }
int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run) int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
{ {
return kvm_handle_cp_32(vcpu, return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs));
cp14_regs, ARRAY_SIZE(cp14_regs),
NULL, 0);
} }
static bool is_imp_def_sys_reg(struct sys_reg_params *params) static bool is_imp_def_sys_reg(struct sys_reg_params *params)
...@@ -2400,14 +2376,8 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params) ...@@ -2400,14 +2376,8 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params)
static int emulate_sys_reg(struct kvm_vcpu *vcpu, static int emulate_sys_reg(struct kvm_vcpu *vcpu,
struct sys_reg_params *params) struct sys_reg_params *params)
{ {
size_t num; const struct sys_reg_desc *r;
const struct sys_reg_desc *table, *r;
table = get_target_table(vcpu->arch.target, true, &num);
/* Search target-specific then generic table. */
r = find_reg(params, table, num);
if (!r)
r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
if (likely(r)) { if (likely(r)) {
...@@ -2512,8 +2482,7 @@ const struct sys_reg_desc *find_reg_by_id(u64 id, ...@@ -2512,8 +2482,7 @@ const struct sys_reg_desc *find_reg_by_id(u64 id,
static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu, static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
u64 id) u64 id)
{ {
size_t num; const struct sys_reg_desc *r;
const struct sys_reg_desc *table, *r;
struct sys_reg_params params; struct sys_reg_params params;
/* We only do sys_reg for now. */ /* We only do sys_reg for now. */
...@@ -2523,9 +2492,6 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu, ...@@ -2523,9 +2492,6 @@ static const struct sys_reg_desc *index_to_sys_reg_desc(struct kvm_vcpu *vcpu,
if (!index_to_params(id, &params)) if (!index_to_params(id, &params))
return NULL; return NULL;
table = get_target_table(vcpu->arch.target, true, &num);
r = find_reg(&params, table, num);
if (!r)
r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); r = find_reg(&params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs));
/* Not saved in the sys_reg array and not otherwise accessible? */ /* Not saved in the sys_reg array and not otherwise accessible? */
...@@ -2826,38 +2792,17 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu, ...@@ -2826,38 +2792,17 @@ static int walk_one_sys_reg(const struct kvm_vcpu *vcpu,
/* Assumed ordered tables, see kvm_sys_reg_table_init. */ /* Assumed ordered tables, see kvm_sys_reg_table_init. */
static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind) static int walk_sys_regs(struct kvm_vcpu *vcpu, u64 __user *uind)
{ {
const struct sys_reg_desc *i1, *i2, *end1, *end2; const struct sys_reg_desc *i2, *end2;
unsigned int total = 0; unsigned int total = 0;
size_t num;
int err; int err;
/* We check for duplicates here, to allow arch-specific overrides. */
i1 = get_target_table(vcpu->arch.target, true, &num);
end1 = i1 + num;
i2 = sys_reg_descs; i2 = sys_reg_descs;
end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs); end2 = sys_reg_descs + ARRAY_SIZE(sys_reg_descs);
if (i1 == end1) while (i2 != end2) {
i1 = NULL; err = walk_one_sys_reg(vcpu, i2++, &uind, &total);
BUG_ON(i2 == end2);
/* Walk carefully, as both tables may refer to the same register. */
while (i1 || i2) {
int cmp = cmp_sys_reg(i1, i2);
/* target-specific overrides generic entry. */
if (cmp <= 0)
err = walk_one_sys_reg(vcpu, i1, &uind, &total);
else
err = walk_one_sys_reg(vcpu, i2, &uind, &total);
if (err) if (err)
return err; return err;
if (cmp <= 0 && ++i1 == end1)
i1 = NULL;
if (cmp >= 0 && ++i2 == end2)
i2 = NULL;
} }
return total; return total;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment