diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-01-21 12:34:22 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-02-29 13:34:22 -0500 |
commit | d06a5440a02cf8ff67b1cd4ee75a30b1b1c66cff (patch) | |
tree | af433aa542ade72a49d2e3e1a3e8977f4a12b2a5 | |
parent | f1d67d4ac79aef6de709d7a21b35851685a1d3ee (diff) |
ARM: KVM: Switch the CP reg search to be a binary search
Doing a linear search is a bit silly when we can do a binary search.
Not that we trap that so many things that it has become a burden yet,
but it makes sense to align it with the arm64 code.
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | arch/arm/kvm/coproc.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c index bb0690271dd2..1bb2b79c01ff 100644 --- a/arch/arm/kvm/coproc.c +++ b/arch/arm/kvm/coproc.c | |||
@@ -16,6 +16,8 @@ | |||
16 | * along with this program; if not, write to the Free Software | 16 | * along with this program; if not, write to the Free Software |
17 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | 17 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
18 | */ | 18 | */ |
19 | |||
20 | #include <linux/bsearch.h> | ||
19 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
20 | #include <linux/kvm_host.h> | 22 | #include <linux/kvm_host.h> |
21 | #include <linux/uaccess.h> | 23 | #include <linux/uaccess.h> |
@@ -414,29 +416,32 @@ static const struct coproc_reg *get_target_table(unsigned target, size_t *num) | |||
414 | return table->table; | 416 | return table->table; |
415 | } | 417 | } |
416 | 418 | ||
419 | #define reg_to_match_value(x) \ | ||
420 | ({ \ | ||
421 | unsigned long val; \ | ||
422 | val = (x)->CRn << 11; \ | ||
423 | val |= (x)->CRm << 7; \ | ||
424 | val |= (x)->Op1 << 4; \ | ||
425 | val |= (x)->Op2 << 1; \ | ||
426 | val |= !(x)->is_64bit; \ | ||
427 | val; \ | ||
428 | }) | ||
429 | |||
430 | static int match_reg(const void *key, const void *elt) | ||
431 | { | ||
432 | const unsigned long pval = (unsigned long)key; | ||
433 | const struct coproc_reg *r = elt; | ||
434 | |||
435 | return pval - reg_to_match_value(r); | ||
436 | } | ||
437 | |||
417 | static const struct coproc_reg *find_reg(const struct coproc_params *params, | 438 | static const struct coproc_reg *find_reg(const struct coproc_params *params, |
418 | const struct coproc_reg table[], | 439 | const struct coproc_reg table[], |
419 | unsigned int num) | 440 | unsigned int num) |
420 | { | 441 | { |
421 | unsigned int i; | 442 | unsigned long pval = reg_to_match_value(params); |
422 | |||
423 | for (i = 0; i < num; i++) { | ||
424 | const struct coproc_reg *r = &table[i]; | ||
425 | 443 | ||
426 | if (params->is_64bit != r->is_64bit) | 444 | return bsearch((void *)pval, table, num, sizeof(table[0]), match_reg); |
427 | continue; | ||
428 | if (params->CRn != r->CRn) | ||
429 | continue; | ||
430 | if (params->CRm != r->CRm) | ||
431 | continue; | ||
432 | if (params->Op1 != r->Op1) | ||
433 | continue; | ||
434 | if (params->Op2 != r->Op2) | ||
435 | continue; | ||
436 | |||
437 | return r; | ||
438 | } | ||
439 | return NULL; | ||
440 | } | 445 | } |
441 | 446 | ||
442 | static int emulate_cp15(struct kvm_vcpu *vcpu, | 447 | static int emulate_cp15(struct kvm_vcpu *vcpu, |