diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2014-01-21 05:55:17 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2014-03-02 20:15:21 -0500 |
commit | 2072d29c46b73e39b3c6c56c6027af77086f45fd (patch) | |
tree | 9c4bbaef5d8fdd56aab396aa46670763271ec3ea | |
parent | 2d58b733c87689d3d5144e4ac94ea861cc729145 (diff) |
arm64: KVM: allows discrimination of AArch32 sysreg access
The current handling of AArch32 trapping is slightly less than
perfect, as it is not possible (from a handler point of view)
to distinguish it from an AArch64 access, nor to tell a 32bit
from a 64bit access either.
Fix this by introducing two additional flags:
- is_aarch32: true if the access was made in AArch32 mode
- is_32bit: true if is_aarch32 == true and a MCR/MRC instruction
was used to perform the access (as opposed to MCRR/MRRC).
This allows a handler to cover all the possible conditions in which
a system register gets trapped.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
-rw-r--r-- | arch/arm64/kvm/sys_regs.c | 6 | ||||
-rw-r--r-- | arch/arm64/kvm/sys_regs.h | 2 |
2 files changed, 8 insertions, 0 deletions
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 02e9d09e1d80..bf03e0fadf1f 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c | |||
@@ -437,6 +437,8 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
437 | u32 hsr = kvm_vcpu_get_hsr(vcpu); | 437 | u32 hsr = kvm_vcpu_get_hsr(vcpu); |
438 | int Rt2 = (hsr >> 10) & 0xf; | 438 | int Rt2 = (hsr >> 10) & 0xf; |
439 | 439 | ||
440 | params.is_aarch32 = true; | ||
441 | params.is_32bit = false; | ||
440 | params.CRm = (hsr >> 1) & 0xf; | 442 | params.CRm = (hsr >> 1) & 0xf; |
441 | params.Rt = (hsr >> 5) & 0xf; | 443 | params.Rt = (hsr >> 5) & 0xf; |
442 | params.is_write = ((hsr & 1) == 0); | 444 | params.is_write = ((hsr & 1) == 0); |
@@ -480,6 +482,8 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
480 | struct sys_reg_params params; | 482 | struct sys_reg_params params; |
481 | u32 hsr = kvm_vcpu_get_hsr(vcpu); | 483 | u32 hsr = kvm_vcpu_get_hsr(vcpu); |
482 | 484 | ||
485 | params.is_aarch32 = true; | ||
486 | params.is_32bit = true; | ||
483 | params.CRm = (hsr >> 1) & 0xf; | 487 | params.CRm = (hsr >> 1) & 0xf; |
484 | params.Rt = (hsr >> 5) & 0xf; | 488 | params.Rt = (hsr >> 5) & 0xf; |
485 | params.is_write = ((hsr & 1) == 0); | 489 | params.is_write = ((hsr & 1) == 0); |
@@ -549,6 +553,8 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
549 | struct sys_reg_params params; | 553 | struct sys_reg_params params; |
550 | unsigned long esr = kvm_vcpu_get_hsr(vcpu); | 554 | unsigned long esr = kvm_vcpu_get_hsr(vcpu); |
551 | 555 | ||
556 | params.is_aarch32 = false; | ||
557 | params.is_32bit = false; | ||
552 | params.Op0 = (esr >> 20) & 3; | 558 | params.Op0 = (esr >> 20) & 3; |
553 | params.Op1 = (esr >> 14) & 0x7; | 559 | params.Op1 = (esr >> 14) & 0x7; |
554 | params.CRn = (esr >> 10) & 0xf; | 560 | params.CRn = (esr >> 10) & 0xf; |
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h index d50d3722998e..d411e251412c 100644 --- a/arch/arm64/kvm/sys_regs.h +++ b/arch/arm64/kvm/sys_regs.h | |||
@@ -30,6 +30,8 @@ struct sys_reg_params { | |||
30 | u8 Op2; | 30 | u8 Op2; |
31 | u8 Rt; | 31 | u8 Rt; |
32 | bool is_write; | 32 | bool is_write; |
33 | bool is_aarch32; | ||
34 | bool is_32bit; /* Only valid if is_aarch32 is true */ | ||
33 | }; | 35 | }; |
34 | 36 | ||
35 | struct sys_reg_desc { | 37 | struct sys_reg_desc { |