[PATCH 1/8] arm64: KVM: Don't skip an instruction if an exception is pending

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



When a trapping instruction has been successfully emulated, we
skip it in order to start executing the following one. Any change
in the PC made while handling the trap (such as injecting an
exception) is going to completely wreck the execution of the
guest by skiping an instruction that hasn't been executed yet.

In order to avoid this, we introduce an "exception_pending" flag,
kept together with the description of the sys_reg that is being
emulated. If that flag gets set, we avoid the skip, making sure we
execute correctly the first instruction of the handler.

Given that nothing sets the flag to true, this patch doesn't change
the existing behaviour yet.

Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx>
---
 arch/arm64/kvm/sys_regs.c | 9 +++++++--
 arch/arm64/kvm/sys_regs.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 0e26f8c2b56f..7ac7fb021dde 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1590,7 +1590,8 @@ static int emulate_cp(struct kvm_vcpu *vcpu,
 
 		if (likely(r->access(vcpu, params, r))) {
 			/* Skip instruction, since it was emulated */
-			kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+			if (!params->exception_pending)
+				kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 			/* Handled */
 			return 0;
 		}
@@ -1645,6 +1646,7 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 	params.is_32bit = false;
 	params.CRm = (hsr >> 1) & 0xf;
 	params.is_write = ((hsr & 1) == 0);
+	params.exception_pending = false;
 
 	params.Op0 = 0;
 	params.Op1 = (hsr >> 16) & 0xf;
@@ -1697,6 +1699,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 	params.CRm = (hsr >> 1) & 0xf;
 	params.regval = vcpu_get_reg(vcpu, Rt);
 	params.is_write = ((hsr & 1) == 0);
+	params.exception_pending = false;
 	params.CRn = (hsr >> 10) & 0xf;
 	params.Op0 = 0;
 	params.Op1 = (hsr >> 14) & 0x7;
@@ -1773,7 +1776,8 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu,
 
 		if (likely(r->access(vcpu, params, r))) {
 			/* Skip instruction, since it was emulated */
-			kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+			if (!params->exception_pending)
+				kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 			return 1;
 		}
 		/* If access function fails, it should complain. */
@@ -1819,6 +1823,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 	params.Op2 = (esr >> 17) & 0x7;
 	params.regval = vcpu_get_reg(vcpu, Rt);
 	params.is_write = !(esr & 1);
+	params.exception_pending = false;
 
 	ret = emulate_sys_reg(vcpu, &params);
 
diff --git a/arch/arm64/kvm/sys_regs.h b/arch/arm64/kvm/sys_regs.h
index 9c6ffd0f0196..c7f790277119 100644
--- a/arch/arm64/kvm/sys_regs.h
+++ b/arch/arm64/kvm/sys_regs.h
@@ -32,6 +32,7 @@ struct sys_reg_params {
 	bool	is_write;
 	bool	is_aarch32;
 	bool	is_32bit;	/* Only valid if is_aarch32 is true */
+	bool	exception_pending;
 };
 
 struct sys_reg_desc {
-- 
2.11.0

_______________________________________________
kvmarm mailing list
kvmarm@xxxxxxxxxxxxxxxxxxxxx
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm



[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux