* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-06 13:01 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:01 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
A little known "feature" of giving guest access to real memory mapped
HW is that it could trigger asynchronous aborts (SError on ARMv8) if
the guest accesses it in a non-conventional way (and depending on how
HW and firmware have been integrated). So far, KVM lacks any support
to handle this gracefully.
This series introduces a set of mechanisms to catch such a fault and
deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
These aborts can either trigger at EL1 (whilst the guest is running),
or at EL2 (during the handling of an exit). The first case is pretty
easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
on arm), but the second one is a bit more fiddly, as we need to ensure
that the exception is pending by the time we unmask it. This is
achived by using some heavy DSBs on the hot path, with the following
caveats:
- I've only been able to trigger the EL2 handling on A57 (Seatle,
Juno).
- I've measured a 40/50 cycles hit on Juno (A57), but I haven't
measured the impact on bigger systems
The last patch of this series adds a missing feature to the
GICV-proxying series, delivering a vSError to a guest that performed
an illegal access to the GIC.
Patches on top of current kvmarm/queue + the GICV przying series.
Marc Zyngier (19):
arm64: KVM: Rename HCR_VA to HCR_VSE
arm64: KVM: Preserve pending vSError in world switch
arm64: KVM: Add Virtual Abort injection helper
arm64: KVM: Add exception code to report EL1 asynchronous aborts
arm64: KVM: Add EL1 async abort handler
arm64: KVM: Route asynchronous aborts
arm64: KVM: Allow an exit code to be tagged with an SError
arm64: KVM: Inject a Virtual SError if it was pending
arm64: KVM: Handle async aborts delivered while at EL2
arm: KVM: Preserve pending Virtual Abort in world switch
arm: KVM: Add Virtual Abort injection helper
arm: KVM: Add HYP async abort handler
arm: KVM: Allow an exit code to be tagged with a Virtual Abort
arm: KVM: Handle async aborts delivered while at HYP
arm: KVM: Inject a Virtual Abort if it was pending
arm: KVM: Drop unreachable HYP abort handlers
arm/arm64: KVM: Inject virtual abort when guest exits on external
abort
arm/arm64: KVM: Remove external abort test from MMIO handling
arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
arch/arm/include/asm/kvm_asm.h | 4 +++
arch/arm/include/asm/kvm_emulate.h | 1 +
arch/arm/kvm/emulate.c | 12 +++++++++
arch/arm/kvm/handle_exit.c | 49 ++++++++++++++++--------------------
arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++
arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++-
arch/arm/kvm/hyp/switch.c | 9 +++++++
arch/arm/kvm/mmio.c | 6 -----
arch/arm/kvm/mmu.c | 5 ++++
arch/arm64/include/asm/kvm_arm.h | 4 +--
arch/arm64/include/asm/kvm_asm.h | 9 +++++--
arch/arm64/include/asm/kvm_emulate.h | 1 +
arch/arm64/include/asm/kvm_hyp.h | 2 +-
arch/arm64/kvm/handle_exit.c | 23 +++++++++++++++++
arch/arm64/kvm/hyp/entry.S | 33 +++++++++++++++++++++++-
arch/arm64/kvm/hyp/hyp-entry.S | 36 ++++++++++++++++++++++----
arch/arm64/kvm/hyp/switch.c | 33 +++++++++++++++++++++---
arch/arm64/kvm/inject_fault.c | 12 +++++++++
virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++----
19 files changed, 254 insertions(+), 53 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-06 13:01 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:01 UTC (permalink / raw)
To: linux-arm-kernel
A little known "feature" of giving guest access to real memory mapped
HW is that it could trigger asynchronous aborts (SError on ARMv8) if
the guest accesses it in a non-conventional way (and depending on how
HW and firmware have been integrated). So far, KVM lacks any support
to handle this gracefully.
This series introduces a set of mechanisms to catch such a fault and
deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
These aborts can either trigger at EL1 (whilst the guest is running),
or at EL2 (during the handling of an exit). The first case is pretty
easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
on arm), but the second one is a bit more fiddly, as we need to ensure
that the exception is pending by the time we unmask it. This is
achived by using some heavy DSBs on the hot path, with the following
caveats:
- I've only been able to trigger the EL2 handling on A57 (Seatle,
Juno).
- I've measured a 40/50 cycles hit on Juno (A57), but I haven't
measured the impact on bigger systems
The last patch of this series adds a missing feature to the
GICV-proxying series, delivering a vSError to a guest that performed
an illegal access to the GIC.
Patches on top of current kvmarm/queue + the GICV przying series.
Marc Zyngier (19):
arm64: KVM: Rename HCR_VA to HCR_VSE
arm64: KVM: Preserve pending vSError in world switch
arm64: KVM: Add Virtual Abort injection helper
arm64: KVM: Add exception code to report EL1 asynchronous aborts
arm64: KVM: Add EL1 async abort handler
arm64: KVM: Route asynchronous aborts
arm64: KVM: Allow an exit code to be tagged with an SError
arm64: KVM: Inject a Virtual SError if it was pending
arm64: KVM: Handle async aborts delivered while at EL2
arm: KVM: Preserve pending Virtual Abort in world switch
arm: KVM: Add Virtual Abort injection helper
arm: KVM: Add HYP async abort handler
arm: KVM: Allow an exit code to be tagged with a Virtual Abort
arm: KVM: Handle async aborts delivered while at HYP
arm: KVM: Inject a Virtual Abort if it was pending
arm: KVM: Drop unreachable HYP abort handlers
arm/arm64: KVM: Inject virtual abort when guest exits on external
abort
arm/arm64: KVM: Remove external abort test from MMIO handling
arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
arch/arm/include/asm/kvm_asm.h | 4 +++
arch/arm/include/asm/kvm_emulate.h | 1 +
arch/arm/kvm/emulate.c | 12 +++++++++
arch/arm/kvm/handle_exit.c | 49 ++++++++++++++++--------------------
arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++
arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++-
arch/arm/kvm/hyp/switch.c | 9 +++++++
arch/arm/kvm/mmio.c | 6 -----
arch/arm/kvm/mmu.c | 5 ++++
arch/arm64/include/asm/kvm_arm.h | 4 +--
arch/arm64/include/asm/kvm_asm.h | 9 +++++--
arch/arm64/include/asm/kvm_emulate.h | 1 +
arch/arm64/include/asm/kvm_hyp.h | 2 +-
arch/arm64/kvm/handle_exit.c | 23 +++++++++++++++++
arch/arm64/kvm/hyp/entry.S | 33 +++++++++++++++++++++++-
arch/arm64/kvm/hyp/hyp-entry.S | 36 ++++++++++++++++++++++----
arch/arm64/kvm/hyp/switch.c | 33 +++++++++++++++++++++---
arch/arm64/kvm/inject_fault.c | 12 +++++++++
virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++----
19 files changed, 254 insertions(+), 53 deletions(-)
--
2.1.4
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 01/19] arm64: KVM: Rename HCR_VA to HCR_VSE
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:01 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:01 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
HCR_VA is a leftover from ARMv7, On ARMv8, this is HCR_VSE
(which stands for Virtual System Error), and has better
defined semantics.
Let's rename the constant.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_arm.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4b5c977..2a2752b 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -50,7 +50,7 @@
#define HCR_BSU (3 << 10)
#define HCR_BSU_IS (UL(1) << 10)
#define HCR_FB (UL(1) << 9)
-#define HCR_VA (UL(1) << 8)
+#define HCR_VSE (UL(1) << 8)
#define HCR_VI (UL(1) << 7)
#define HCR_VF (UL(1) << 6)
#define HCR_AMO (UL(1) << 5)
@@ -80,7 +80,7 @@
#define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
-#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
#define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO)
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 01/19] arm64: KVM: Rename HCR_VA to HCR_VSE
@ 2016-09-06 13:01 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:01 UTC (permalink / raw)
To: linux-arm-kernel
HCR_VA is a leftover from ARMv7, On ARMv8, this is HCR_VSE
(which stands for Virtual System Error), and has better
defined semantics.
Let's rename the constant.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_arm.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h
index 4b5c977..2a2752b 100644
--- a/arch/arm64/include/asm/kvm_arm.h
+++ b/arch/arm64/include/asm/kvm_arm.h
@@ -50,7 +50,7 @@
#define HCR_BSU (3 << 10)
#define HCR_BSU_IS (UL(1) << 10)
#define HCR_FB (UL(1) << 9)
-#define HCR_VA (UL(1) << 8)
+#define HCR_VSE (UL(1) << 8)
#define HCR_VI (UL(1) << 7)
#define HCR_VF (UL(1) << 6)
#define HCR_AMO (UL(1) << 5)
@@ -80,7 +80,7 @@
#define HCR_GUEST_FLAGS (HCR_TSC | HCR_TSW | HCR_TWE | HCR_TWI | HCR_VM | \
HCR_TVM | HCR_BSU_IS | HCR_FB | HCR_TAC | \
HCR_AMO | HCR_SWIO | HCR_TIDCP | HCR_RW)
-#define HCR_VIRT_EXCP_MASK (HCR_VA | HCR_VI | HCR_VF)
+#define HCR_VIRT_EXCP_MASK (HCR_VSE | HCR_VI | HCR_VF)
#define HCR_INT_OVERRIDE (HCR_FMO | HCR_IMO)
#define HCR_HOST_VHE_FLAGS (HCR_RW | HCR_TGE | HCR_E2H)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 02/19] arm64: KVM: Preserve pending vSError in world switch
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
The HCR_EL2.VSE bit is used to signal an SError to a guest, and has
the peculiar feature of getting cleared when the guest has taken
the abort (this is the only bit that behaves as such in this register).
This means that if we signal such an abort, we must leave it
in the guest context until it disappears from HCR_EL2, and at which
point it must be cleared from the context. This is achieved by
reading back from HCR_EL2 until the guest takes the fault.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/switch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index fcb7aae..5148b06 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -110,6 +110,15 @@ static hyp_alternate_select(__deactivate_traps_arch,
static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
{
+ /*
+ * If we pended a virtual abort, preserve it until it gets
+ * cleared. See D1.14.3 (Virtual Interrupts) for details, but
+ * the crucial bit is "On taking a vSError interrupt,
+ * HCR_EL2.VSE is cleared to 0."
+ */
+ if (vcpu->arch.hcr_el2 & HCR_VSE)
+ vcpu->arch.hcr_el2 = read_sysreg(hcr_el2);
+
__deactivate_traps_arch()();
write_sysreg(0, hstr_el2);
write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 02/19] arm64: KVM: Preserve pending vSError in world switch
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
The HCR_EL2.VSE bit is used to signal an SError to a guest, and has
the peculiar feature of getting cleared when the guest has taken
the abort (this is the only bit that behaves as such in this register).
This means that if we signal such an abort, we must leave it
in the guest context until it disappears from HCR_EL2, and at which
point it must be cleared from the context. This is achieved by
reading back from HCR_EL2 until the guest takes the fault.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/switch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index fcb7aae..5148b06 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -110,6 +110,15 @@ static hyp_alternate_select(__deactivate_traps_arch,
static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
{
+ /*
+ * If we pended a virtual abort, preserve it until it gets
+ * cleared. See D1.14.3 (Virtual Interrupts) for details, but
+ * the crucial bit is "On taking a vSError interrupt,
+ * HCR_EL2.VSE is cleared to 0."
+ */
+ if (vcpu->arch.hcr_el2 & HCR_VSE)
+ vcpu->arch.hcr_el2 = read_sysreg(hcr_el2);
+
__deactivate_traps_arch()();
write_sysreg(0, hstr_el2);
write_sysreg(read_sysreg(mdcr_el2) & MDCR_EL2_HPMN_MASK, mdcr_el2);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 03/19] arm64: KVM: Add Virtual Abort injection helper
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
Now that we're able to context switch the HCR_EL2.VA bit, let's
introduce a helper that injects an Abort into a vcpu.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_emulate.h | 1 +
arch/arm64/kvm/inject_fault.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index b336434d..fd9d5fd 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -38,6 +38,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_vabt(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 898c0e6..da6a8cf 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -231,3 +231,15 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
else
inject_undef64(vcpu);
}
+
+/**
+ * kvm_inject_vabt - inject an async abort / SError into the guest
+ * @vcpu: The VCPU to receive the exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_vabt(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) | HCR_VSE);
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 03/19] arm64: KVM: Add Virtual Abort injection helper
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Now that we're able to context switch the HCR_EL2.VA bit, let's
introduce a helper that injects an Abort into a vcpu.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_emulate.h | 1 +
arch/arm64/kvm/inject_fault.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index b336434d..fd9d5fd 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -38,6 +38,7 @@ bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_vabt(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c
index 898c0e6..da6a8cf 100644
--- a/arch/arm64/kvm/inject_fault.c
+++ b/arch/arm64/kvm/inject_fault.c
@@ -231,3 +231,15 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu)
else
inject_undef64(vcpu);
}
+
+/**
+ * kvm_inject_vabt - inject an async abort / SError into the guest
+ * @vcpu: The VCPU to receive the exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_vabt(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) | HCR_VSE);
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 04/19] arm64: KVM: Add exception code to report EL1 asynchronous aborts
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
So far, we don't have a code to indicate that we've taken an
asynchronous abort from EL1. Let's add one.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_asm.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 7561f63..d177e7e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -21,9 +21,10 @@
#include <asm/virt.h>
#define ARM_EXCEPTION_IRQ 0
-#define ARM_EXCEPTION_TRAP 1
+#define ARM_EXCEPTION_EL1_SERROR 1
+#define ARM_EXCEPTION_TRAP 2
/* The hyp-stub will return this for any kvm_call_hyp() call */
-#define ARM_EXCEPTION_HYP_GONE 2
+#define ARM_EXCEPTION_HYP_GONE 3
#define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
#define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 04/19] arm64: KVM: Add exception code to report EL1 asynchronous aborts
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
So far, we don't have a code to indicate that we've taken an
asynchronous abort from EL1. Let's add one.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_asm.h | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index 7561f63..d177e7e 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -21,9 +21,10 @@
#include <asm/virt.h>
#define ARM_EXCEPTION_IRQ 0
-#define ARM_EXCEPTION_TRAP 1
+#define ARM_EXCEPTION_EL1_SERROR 1
+#define ARM_EXCEPTION_TRAP 2
/* The hyp-stub will return this for any kvm_call_hyp() call */
-#define ARM_EXCEPTION_HYP_GONE 2
+#define ARM_EXCEPTION_HYP_GONE 3
#define KVM_ARM64_DEBUG_DIRTY_SHIFT 0
#define KVM_ARM64_DEBUG_DIRTY (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 05/19] arm64: KVM: Add EL1 async abort handler
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If we've exited the guest because it has triggered an asynchronous
abort from EL1, a possible course of action is to let it know it
screwed up by giving it a Virtual Abort to chew on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/handle_exit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index fa96fe2b..08afc69a 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -173,6 +173,9 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
+ case ARM_EXCEPTION_EL1_SERROR:
+ kvm_inject_vabt(vcpu);
+ return 1;
case ARM_EXCEPTION_TRAP:
/*
* See ARM ARM B1.14.1: "Hyp traps on instructions
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 05/19] arm64: KVM: Add EL1 async abort handler
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If we've exited the guest because it has triggered an asynchronous
abort from EL1, a possible course of action is to let it know it
screwed up by giving it a Virtual Abort to chew on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/handle_exit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index fa96fe2b..08afc69a 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -173,6 +173,9 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
+ case ARM_EXCEPTION_EL1_SERROR:
+ kvm_inject_vabt(vcpu);
+ return 1;
case ARM_EXCEPTION_TRAP:
/*
* See ARM ARM B1.14.1: "Hyp traps on instructions
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 06/19] arm64: KVM: Route asynchronous aborts
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
As we now have some basic handling to EL1-triggered aborts, we can
actually report them to KVM.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/hyp-entry.S | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index d6cae54..d2f6640 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -120,6 +120,12 @@ el1_irq:
mov x0, #ARM_EXCEPTION_IRQ
b __guest_exit
+el1_error:
+ stp x0, x1, [sp, #-16]!
+ mrs x1, tpidr_el2
+ mov x0, #ARM_EXCEPTION_EL1_SERROR
+ b __guest_exit
+
ENTRY(__hyp_do_panic)
mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h)
@@ -148,7 +154,6 @@ ENDPROC(\label)
invalid_vector el1_sync_invalid
invalid_vector el1_irq_invalid
invalid_vector el1_fiq_invalid
- invalid_vector el1_error_invalid
.ltorg
@@ -168,10 +173,10 @@ ENTRY(__kvm_hyp_vector)
ventry el1_sync // Synchronous 64-bit EL1
ventry el1_irq // IRQ 64-bit EL1
ventry el1_fiq_invalid // FIQ 64-bit EL1
- ventry el1_error_invalid // Error 64-bit EL1
+ ventry el1_error // Error 64-bit EL1
ventry el1_sync // Synchronous 32-bit EL1
ventry el1_irq // IRQ 32-bit EL1
ventry el1_fiq_invalid // FIQ 32-bit EL1
- ventry el1_error_invalid // Error 32-bit EL1
+ ventry el1_error // Error 32-bit EL1
ENDPROC(__kvm_hyp_vector)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 06/19] arm64: KVM: Route asynchronous aborts
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
As we now have some basic handling to EL1-triggered aborts, we can
actually report them to KVM.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/hyp-entry.S | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index d6cae54..d2f6640 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -120,6 +120,12 @@ el1_irq:
mov x0, #ARM_EXCEPTION_IRQ
b __guest_exit
+el1_error:
+ stp x0, x1, [sp, #-16]!
+ mrs x1, tpidr_el2
+ mov x0, #ARM_EXCEPTION_EL1_SERROR
+ b __guest_exit
+
ENTRY(__hyp_do_panic)
mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h)
@@ -148,7 +154,6 @@ ENDPROC(\label)
invalid_vector el1_sync_invalid
invalid_vector el1_irq_invalid
invalid_vector el1_fiq_invalid
- invalid_vector el1_error_invalid
.ltorg
@@ -168,10 +173,10 @@ ENTRY(__kvm_hyp_vector)
ventry el1_sync // Synchronous 64-bit EL1
ventry el1_irq // IRQ 64-bit EL1
ventry el1_fiq_invalid // FIQ 64-bit EL1
- ventry el1_error_invalid // Error 64-bit EL1
+ ventry el1_error // Error 64-bit EL1
ventry el1_sync // Synchronous 32-bit EL1
ventry el1_irq // IRQ 32-bit EL1
ventry el1_fiq_invalid // FIQ 32-bit EL1
- ventry el1_error_invalid // Error 32-bit EL1
+ ventry el1_error // Error 32-bit EL1
ENDPROC(__kvm_hyp_vector)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 07/19] arm64: KVM: Allow an exit code to be tagged with an SError
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
Similarily to EL1, an asynchronous abort can be triggered whilst
running at EL2. But instead of making that a new error code,
we need to communicate it to the rest of KVM together with
the exit reason. So let's hijack a single bit that allows the
exception code to be tagged with a "pending SError" information.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_asm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index d177e7e..18f7465 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -20,6 +20,10 @@
#include <asm/virt.h>
+#define ARM_EXIT_WITH_SERROR_BIT 31
+#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT))
+#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT))
+
#define ARM_EXCEPTION_IRQ 0
#define ARM_EXCEPTION_EL1_SERROR 1
#define ARM_EXCEPTION_TRAP 2
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 07/19] arm64: KVM: Allow an exit code to be tagged with an SError
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Similarily to EL1, an asynchronous abort can be triggered whilst
running at EL2. But instead of making that a new error code,
we need to communicate it to the rest of KVM together with
the exit reason. So let's hijack a single bit that allows the
exception code to be tagged with a "pending SError" information.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_asm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h
index d177e7e..18f7465 100644
--- a/arch/arm64/include/asm/kvm_asm.h
+++ b/arch/arm64/include/asm/kvm_asm.h
@@ -20,6 +20,10 @@
#include <asm/virt.h>
+#define ARM_EXIT_WITH_SERROR_BIT 31
+#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_SERROR_BIT))
+#define ARM_SERROR_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_SERROR_BIT))
+
#define ARM_EXCEPTION_IRQ 0
#define ARM_EXCEPTION_EL1_SERROR 1
#define ARM_EXCEPTION_TRAP 2
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 08/19] arm64: KVM: Inject a Virtual SError if it was pending
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
If we have caught an SError whilst exiting, we've tagged the
exit code with the pending information. In that case, let's
re-inject the error into the guest, after having adjusted
the PC if required.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/handle_exit.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 08afc69a..a204adf 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -170,6 +170,26 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
exit_handle_fn exit_handler;
+ if (ARM_SERROR_PENDING(exception_index)) {
+ u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
+
+ /*
+ * HVC/SMC already have an adjusted PC, which we need
+ * to correct in order to return to after having
+ * injected the SError.
+ */
+ if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 ||
+ hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) {
+ u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
+ *vcpu_pc(vcpu) -= adj;
+ }
+
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
+ exception_index = ARM_EXCEPTION_CODE(exception_index);
+
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 08/19] arm64: KVM: Inject a Virtual SError if it was pending
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If we have caught an SError whilst exiting, we've tagged the
exit code with the pending information. In that case, let's
re-inject the error into the guest, after having adjusted
the PC if required.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/handle_exit.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 08afc69a..a204adf 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -170,6 +170,26 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
exit_handle_fn exit_handler;
+ if (ARM_SERROR_PENDING(exception_index)) {
+ u8 hsr_ec = ESR_ELx_EC(kvm_vcpu_get_hsr(vcpu));
+
+ /*
+ * HVC/SMC already have an adjusted PC, which we need
+ * to correct in order to return to after having
+ * injected the SError.
+ */
+ if (hsr_ec == ESR_ELx_EC_HVC32 || hsr_ec == ESR_ELx_EC_HVC64 ||
+ hsr_ec == ESR_ELx_EC_SMC32 || hsr_ec == ESR_ELx_EC_SMC64) {
+ u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
+ *vcpu_pc(vcpu) -= adj;
+ }
+
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
+ exception_index = ARM_EXCEPTION_CODE(exception_index);
+
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If EL1 generates an asynchronous abort and then traps into EL2
before the abort has been delivered, we may end-up with the
abort firing at the worse possible place: on the host.
In order to avoid this, it is necessary to take the abort at EL2,
by clearing the PSTATE.A bit. In order to survive this abort,
we do it at a point where we're in a known state with respect
to the world switch, and handle the resulting exception,
overloading the exit code in the process.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
arch/arm64/kvm/hyp/switch.c | 6 ++++++
3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 3967c231..7662ef5 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -122,7 +122,38 @@ ENTRY(__guest_exit)
// Now restore the host regs
restore_callee_saved_regs x2
- ret
+ // If we have a pending asynchronous abort, now is the
+ // time to find out. From your VAXorcist book, page 666:
+ // "Threaten me not, oh Evil one! For I speak with
+ // the power of DEC, and I command thee to show thyself!"
+ mrs x2, elr_el2
+ mrs x3, esr_el2
+ mrs x4, spsr_el2
+ mov x5, x0
+
+ dsb sy // Synchronize against in-flight ld/st
+ msr daifclr, #4 // Unmask aborts
+
+ // This is our single instruction exception window. A pending
+ // SError is guaranteed to occur at the earliest when we unmask
+ // it, and at the latest just after the ISB.
+ .global abort_guest_exit_start
+abort_guest_exit_start:
+
+ isb
+
+ .global abort_guest_exit_end
+abort_guest_exit_end:
+
+ // If the exception took place, restore the EL1 exception
+ // context so that we can report some information.
+ // Merge the exception code with the SError pending bit.
+ tbz x0, #ARM_EXIT_WITH_SERROR_BIT, 1f
+ msr elr_el2, x2
+ msr esr_el2, x3
+ msr spsr_el2, x4
+ orr x0, x0, x5
+1: ret
ENDPROC(__guest_exit)
ENTRY(__fpsimd_guest_restore)
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index d2f6640..4e92399 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -126,6 +126,28 @@ el1_error:
mov x0, #ARM_EXCEPTION_EL1_SERROR
b __guest_exit
+el2_error:
+ /*
+ * Only two possibilities:
+ * 1) Either we come from the exit path, having just unmasked
+ * PSTATE.A: change the return code to an EL2 fault, and
+ * carry on, as we're already in a sane state to handle it.
+ * 2) Or we come from anywhere else, and that's a bug: we panic.
+ *
+ * For (1), x0 contains the original return code and x1 doesn't
+ * contain anything meaningful at that stage. We can reuse them
+ * as temp registers.
+ * For (2), who cares?
+ */
+ mrs x0, elr_el2
+ adr x1, abort_guest_exit_start
+ cmp x0, x1
+ adr x1, abort_guest_exit_end
+ ccmp x0, x1, #4, ne
+ b.ne __hyp_panic
+ mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
+ eret
+
ENTRY(__hyp_do_panic)
mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h)
@@ -150,7 +172,6 @@ ENDPROC(\label)
invalid_vector el2h_sync_invalid
invalid_vector el2h_irq_invalid
invalid_vector el2h_fiq_invalid
- invalid_vector el2h_error_invalid
invalid_vector el1_sync_invalid
invalid_vector el1_irq_invalid
invalid_vector el1_fiq_invalid
@@ -168,7 +189,7 @@ ENTRY(__kvm_hyp_vector)
ventry el2h_sync_invalid // Synchronous EL2h
ventry el2h_irq_invalid // IRQ EL2h
ventry el2h_fiq_invalid // FIQ EL2h
- ventry el2h_error_invalid // Error EL2h
+ ventry el2_error // Error EL2h
ventry el1_sync // Synchronous 64-bit EL1
ventry el1_irq // IRQ 64-bit EL1
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 5148b06..1233a55 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -292,6 +292,12 @@ again:
exit_code = __guest_enter(vcpu, host_ctxt);
/* And we're baaack! */
+ /*
+ * We're using the raw exception code in order to only process
+ * the trap if no SError is pending. We will come back to the
+ * same PC once the SError has been injected, and replay the
+ * trapping instruction.
+ */
if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
goto again;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If EL1 generates an asynchronous abort and then traps into EL2
before the abort has been delivered, we may end-up with the
abort firing at the worse possible place: on the host.
In order to avoid this, it is necessary to take the abort at EL2,
by clearing the PSTATE.A bit. In order to survive this abort,
we do it at a point where we're in a known state with respect
to the world switch, and handle the resulting exception,
overloading the exit code in the process.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
arch/arm64/kvm/hyp/switch.c | 6 ++++++
3 files changed, 61 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
index 3967c231..7662ef5 100644
--- a/arch/arm64/kvm/hyp/entry.S
+++ b/arch/arm64/kvm/hyp/entry.S
@@ -122,7 +122,38 @@ ENTRY(__guest_exit)
// Now restore the host regs
restore_callee_saved_regs x2
- ret
+ // If we have a pending asynchronous abort, now is the
+ // time to find out. From your VAXorcist book, page 666:
+ // "Threaten me not, oh Evil one! For I speak with
+ // the power of DEC, and I command thee to show thyself!"
+ mrs x2, elr_el2
+ mrs x3, esr_el2
+ mrs x4, spsr_el2
+ mov x5, x0
+
+ dsb sy // Synchronize against in-flight ld/st
+ msr daifclr, #4 // Unmask aborts
+
+ // This is our single instruction exception window. A pending
+ // SError is guaranteed to occur at the earliest when we unmask
+ // it, and at the latest just after the ISB.
+ .global abort_guest_exit_start
+abort_guest_exit_start:
+
+ isb
+
+ .global abort_guest_exit_end
+abort_guest_exit_end:
+
+ // If the exception took place, restore the EL1 exception
+ // context so that we can report some information.
+ // Merge the exception code with the SError pending bit.
+ tbz x0, #ARM_EXIT_WITH_SERROR_BIT, 1f
+ msr elr_el2, x2
+ msr esr_el2, x3
+ msr spsr_el2, x4
+ orr x0, x0, x5
+1: ret
ENDPROC(__guest_exit)
ENTRY(__fpsimd_guest_restore)
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
index d2f6640..4e92399 100644
--- a/arch/arm64/kvm/hyp/hyp-entry.S
+++ b/arch/arm64/kvm/hyp/hyp-entry.S
@@ -126,6 +126,28 @@ el1_error:
mov x0, #ARM_EXCEPTION_EL1_SERROR
b __guest_exit
+el2_error:
+ /*
+ * Only two possibilities:
+ * 1) Either we come from the exit path, having just unmasked
+ * PSTATE.A: change the return code to an EL2 fault, and
+ * carry on, as we're already in a sane state to handle it.
+ * 2) Or we come from anywhere else, and that's a bug: we panic.
+ *
+ * For (1), x0 contains the original return code and x1 doesn't
+ * contain anything meaningful at that stage. We can reuse them
+ * as temp registers.
+ * For (2), who cares?
+ */
+ mrs x0, elr_el2
+ adr x1, abort_guest_exit_start
+ cmp x0, x1
+ adr x1, abort_guest_exit_end
+ ccmp x0, x1, #4, ne
+ b.ne __hyp_panic
+ mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
+ eret
+
ENTRY(__hyp_do_panic)
mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
PSR_MODE_EL1h)
@@ -150,7 +172,6 @@ ENDPROC(\label)
invalid_vector el2h_sync_invalid
invalid_vector el2h_irq_invalid
invalid_vector el2h_fiq_invalid
- invalid_vector el2h_error_invalid
invalid_vector el1_sync_invalid
invalid_vector el1_irq_invalid
invalid_vector el1_fiq_invalid
@@ -168,7 +189,7 @@ ENTRY(__kvm_hyp_vector)
ventry el2h_sync_invalid // Synchronous EL2h
ventry el2h_irq_invalid // IRQ EL2h
ventry el2h_fiq_invalid // FIQ EL2h
- ventry el2h_error_invalid // Error EL2h
+ ventry el2_error // Error EL2h
ventry el1_sync // Synchronous 64-bit EL1
ventry el1_irq // IRQ 64-bit EL1
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 5148b06..1233a55 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -292,6 +292,12 @@ again:
exit_code = __guest_enter(vcpu, host_ctxt);
/* And we're baaack! */
+ /*
+ * We're using the raw exception code in order to only process
+ * the trap if no SError is pending. We will come back to the
+ * same PC once the SError has been injected, and replay the
+ * trapping instruction.
+ */
if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
goto again;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 10/19] arm: KVM: Preserve pending Virtual Abort in world switch
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
The HCR.VA bit is used to signal an Abort to a guest, and has
the peculiar feature of getting cleared when the guest has taken
the abort (this is the only bit that behaves as such in this register).
This means that if we signal such an abort, we must leave it in
the guest context until it disappears from HCR, and at which point
it must be cleared from the context.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/hyp/switch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
index b13caa9..8cda887 100644
--- a/arch/arm/kvm/hyp/switch.c
+++ b/arch/arm/kvm/hyp/switch.c
@@ -54,6 +54,15 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
{
u32 val;
+ /*
+ * If we pended a virtual abort, preserve it until it gets
+ * cleared. See B1.9.9 (Virtual Abort exception) for details,
+ * but the crucial bit is the zeroing of HCR.VA in the
+ * pseudocode.
+ */
+ if (vcpu->arch.hcr & HCR_VA)
+ vcpu->arch.hcr = read_sysreg(HCR);
+
write_sysreg(0, HCR);
write_sysreg(0, HSTR);
val = read_sysreg(HDCR);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 10/19] arm: KVM: Preserve pending Virtual Abort in world switch
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
The HCR.VA bit is used to signal an Abort to a guest, and has
the peculiar feature of getting cleared when the guest has taken
the abort (this is the only bit that behaves as such in this register).
This means that if we signal such an abort, we must leave it in
the guest context until it disappears from HCR, and at which point
it must be cleared from the context.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/hyp/switch.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
index b13caa9..8cda887 100644
--- a/arch/arm/kvm/hyp/switch.c
+++ b/arch/arm/kvm/hyp/switch.c
@@ -54,6 +54,15 @@ static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
{
u32 val;
+ /*
+ * If we pended a virtual abort, preserve it until it gets
+ * cleared. See B1.9.9 (Virtual Abort exception) for details,
+ * but the crucial bit is the zeroing of HCR.VA in the
+ * pseudocode.
+ */
+ if (vcpu->arch.hcr & HCR_VA)
+ vcpu->arch.hcr = read_sysreg(HCR);
+
write_sysreg(0, HCR);
write_sysreg(0, HSTR);
val = read_sysreg(HDCR);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 11/19] arm: KVM: Add Virtual Abort injection helper
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
Now that we're able to context switch the HCR.VA bit, let's
introduce a helper that injects an Abort into a vcpu.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/kvm_emulate.h | 1 +
arch/arm/kvm/emulate.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 448d63c..9a8a45a 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -43,6 +43,7 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_vabt(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index ff9acd1..0064b86 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -303,3 +303,15 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
{
inject_abt(vcpu, true, addr);
}
+
+/**
+ * kvm_inject_vabt - inject an async abort / SError into the guest
+ * @vcpu: The VCPU to receive the exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_vabt(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) | HCR_VA);
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 11/19] arm: KVM: Add Virtual Abort injection helper
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Now that we're able to context switch the HCR.VA bit, let's
introduce a helper that injects an Abort into a vcpu.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/kvm_emulate.h | 1 +
arch/arm/kvm/emulate.c | 12 ++++++++++++
2 files changed, 13 insertions(+)
diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index 448d63c..9a8a45a 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -43,6 +43,7 @@ static inline void vcpu_set_reg(struct kvm_vcpu *vcpu, u8 reg_num,
bool kvm_condition_valid32(const struct kvm_vcpu *vcpu);
void kvm_skip_instr32(struct kvm_vcpu *vcpu, bool is_wide_instr);
void kvm_inject_undefined(struct kvm_vcpu *vcpu);
+void kvm_inject_vabt(struct kvm_vcpu *vcpu);
void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c
index ff9acd1..0064b86 100644
--- a/arch/arm/kvm/emulate.c
+++ b/arch/arm/kvm/emulate.c
@@ -303,3 +303,15 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr)
{
inject_abt(vcpu, true, addr);
}
+
+/**
+ * kvm_inject_vabt - inject an async abort / SError into the guest
+ * @vcpu: The VCPU to receive the exception
+ *
+ * It is assumed that this code is called from the VCPU thread and that the
+ * VCPU therefore is not currently executing guest code.
+ */
+void kvm_inject_vabt(struct kvm_vcpu *vcpu)
+{
+ vcpu_set_hcr(vcpu, vcpu_get_hcr(vcpu) | HCR_VA);
+}
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 12/19] arm: KVM: Add HYP async abort handler
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If we've exited the guest because it has triggered an asynchronous
abort, a possible course of action is to let it know it screwed up
by giving it a Virtual Abort to chew on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 3f1ef0d..863fdf4 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -160,6 +160,9 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
exit_handler = kvm_get_exit_handler(vcpu);
return exit_handler(vcpu, run);
+ case ARM_EXCEPTION_DATA_ABORT:
+ kvm_inject_vabt(vcpu);
+ return 1;
default:
kvm_pr_unimpl("Unsupported exception type: %d",
exception_index);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 12/19] arm: KVM: Add HYP async abort handler
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If we've exited the guest because it has triggered an asynchronous
abort, a possible course of action is to let it know it screwed up
by giving it a Virtual Abort to chew on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 3f1ef0d..863fdf4 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -160,6 +160,9 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
exit_handler = kvm_get_exit_handler(vcpu);
return exit_handler(vcpu, run);
+ case ARM_EXCEPTION_DATA_ABORT:
+ kvm_inject_vabt(vcpu);
+ return 1;
default:
kvm_pr_unimpl("Unsupported exception type: %d",
exception_index);
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 13/19] arm: KVM: Allow an exit code to be tagged with a Virtual Abort
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
An asynchronous abort can also be triggered whilst running at EL2.
But instead of making that a new error code, we need to communicate
it to the rest of KVM together with the exit reason.
So let's hijack a single bit that allows the exception code to be
tagged with a "pending Abort" information.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/kvm_asm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 58faff5..05e47fa 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -21,6 +21,10 @@
#include <asm/virt.h>
+#define ARM_EXIT_WITH_ABORT_BIT 31
+#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_ABORT_BIT))
+#define ARM_ABORT_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_ABORT_BIT))
+
#define ARM_EXCEPTION_RESET 0
#define ARM_EXCEPTION_UNDEFINED 1
#define ARM_EXCEPTION_SOFTWARE 2
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 13/19] arm: KVM: Allow an exit code to be tagged with a Virtual Abort
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
An asynchronous abort can also be triggered whilst running at EL2.
But instead of making that a new error code, we need to communicate
it to the rest of KVM together with the exit reason.
So let's hijack a single bit that allows the exception code to be
tagged with a "pending Abort" information.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/include/asm/kvm_asm.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 58faff5..05e47fa 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -21,6 +21,10 @@
#include <asm/virt.h>
+#define ARM_EXIT_WITH_ABORT_BIT 31
+#define ARM_EXCEPTION_CODE(x) ((x) & ~(1U << ARM_EXIT_WITH_ABORT_BIT))
+#define ARM_ABORT_PENDING(x) !!((x) & (1U << ARM_EXIT_WITH_ABORT_BIT))
+
#define ARM_EXCEPTION_RESET 0
#define ARM_EXCEPTION_UNDEFINED 1
#define ARM_EXCEPTION_SOFTWARE 2
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 14/19] arm: KVM: Handle async aborts delivered while at HYP
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
Just like for arm64, we can handle asynchronous aborts being
delivered at HYP while being caused by the guest. We use
the exact same method to catch such an abort, and soldier on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++++++++++
arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++++++-
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/hyp/entry.S b/arch/arm/kvm/hyp/entry.S
index 21c2388..60783f3 100644
--- a/arch/arm/kvm/hyp/entry.S
+++ b/arch/arm/kvm/hyp/entry.S
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
.arch_extension virt
@@ -63,6 +64,36 @@ ENTRY(__guest_exit)
ldr lr, [r0, #4]
mov r0, r1
+ mrs r1, SPSR
+ mrs r2, ELR_hyp
+ mrc p15, 4, r3, c5, c2, 0 @ HSR
+
+ /*
+ * Force loads and stores to complete before unmasking aborts
+ * and forcing the delivery of the exception. This gives us a
+ * single instruction window, which the handler will try to
+ * match.
+ */
+ dsb sy
+ cpsie a
+
+ .global abort_guest_exit_start
+abort_guest_exit_start:
+
+ isb
+
+ .global abort_guest_exit_end
+abort_guest_exit_end:
+
+ /*
+ * If we took an abort, r0[31] will be set, and cmp will set
+ * the N bit in PSTATE.
+ */
+ cmp r0, #0
+ msrmi SPSR_cxsf, r1
+ msrmi ELR_hyp, r2
+ mcrmi p15, 4, r3, c5, c2, 0 @ HSR
+
bx lr
ENDPROC(__guest_exit)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 7809138..96beb53 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -81,7 +81,6 @@ __kvm_hyp_vector:
invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED
invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE
invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT
- invalid_vector hyp_dabt ARM_EXCEPTION_DATA_ABORT
invalid_vector hyp_fiq ARM_EXCEPTION_FIQ
ENTRY(__hyp_do_panic)
@@ -164,6 +163,21 @@ hyp_irq:
load_vcpu r0 @ Load VCPU pointer to r0
b __guest_exit
+hyp_dabt:
+ push {r0, r1}
+ mrs r0, ELR_hyp
+ ldr r1, =abort_guest_exit_start
+THUMB( add r1, r1, #1)
+ cmp r0, r1
+ ldrne r1, =abort_guest_exit_end
+THUMB( addne r1, r1, #1)
+ cmpne r0, r1
+ pop {r0, r1}
+ bne __hyp_panic
+
+ orr r0, r0, #(1 << ARM_EXIT_WITH_ABORT_BIT)
+ eret
+
.ltorg
.popsection
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 14/19] arm: KVM: Handle async aborts delivered while at HYP
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Just like for arm64, we can handle asynchronous aborts being
delivered at HYP while being caused by the guest. We use
the exact same method to catch such an abort, and soldier on.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++++++++++
arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++++++-
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/arch/arm/kvm/hyp/entry.S b/arch/arm/kvm/hyp/entry.S
index 21c2388..60783f3 100644
--- a/arch/arm/kvm/hyp/entry.S
+++ b/arch/arm/kvm/hyp/entry.S
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
.arch_extension virt
@@ -63,6 +64,36 @@ ENTRY(__guest_exit)
ldr lr, [r0, #4]
mov r0, r1
+ mrs r1, SPSR
+ mrs r2, ELR_hyp
+ mrc p15, 4, r3, c5, c2, 0 @ HSR
+
+ /*
+ * Force loads and stores to complete before unmasking aborts
+ * and forcing the delivery of the exception. This gives us a
+ * single instruction window, which the handler will try to
+ * match.
+ */
+ dsb sy
+ cpsie a
+
+ .global abort_guest_exit_start
+abort_guest_exit_start:
+
+ isb
+
+ .global abort_guest_exit_end
+abort_guest_exit_end:
+
+ /*
+ * If we took an abort, r0[31] will be set, and cmp will set
+ * the N bit in PSTATE.
+ */
+ cmp r0, #0
+ msrmi SPSR_cxsf, r1
+ msrmi ELR_hyp, r2
+ mcrmi p15, 4, r3, c5, c2, 0 @ HSR
+
bx lr
ENDPROC(__guest_exit)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 7809138..96beb53 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -81,7 +81,6 @@ __kvm_hyp_vector:
invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED
invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE
invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT
- invalid_vector hyp_dabt ARM_EXCEPTION_DATA_ABORT
invalid_vector hyp_fiq ARM_EXCEPTION_FIQ
ENTRY(__hyp_do_panic)
@@ -164,6 +163,21 @@ hyp_irq:
load_vcpu r0 @ Load VCPU pointer to r0
b __guest_exit
+hyp_dabt:
+ push {r0, r1}
+ mrs r0, ELR_hyp
+ ldr r1, =abort_guest_exit_start
+THUMB( add r1, r1, #1)
+ cmp r0, r1
+ ldrne r1, =abort_guest_exit_end
+THUMB( addne r1, r1, #1)
+ cmpne r0, r1
+ pop {r0, r1}
+ bne __hyp_panic
+
+ orr r0, r0, #(1 << ARM_EXIT_WITH_ABORT_BIT)
+ eret
+
.ltorg
.popsection
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 15/19] arm: KVM: Inject a Virtual Abort if it was pending
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If we have caught an Abort whilst exiting, we've tagged the
exit code with the pending information. In that case, let's
re-inject the error into the guest, after having adjusted
the PC if required.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 863fdf4..4eacb5c 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -144,6 +144,25 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
exit_handle_fn exit_handler;
+ if (ARM_ABORT_PENDING(exception_index)) {
+ u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+
+ /*
+ * HVC/SMC already have an adjusted PC, which we need
+ * to correct in order to return to after having
+ * injected the abort.
+ */
+ if (hsr_ec == HSR_EC_HVC || hsr_ec == HSR_EC_SMC) {
+ u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
+ *vcpu_pc(vcpu) -= adj;
+ }
+
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
+ exception_index = ARM_EXCEPTION_CODE(exception_index);
+
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 15/19] arm: KVM: Inject a Virtual Abort if it was pending
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If we have caught an Abort whilst exiting, we've tagged the
exit code with the pending information. In that case, let's
re-inject the error into the guest, after having adjusted
the PC if required.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 863fdf4..4eacb5c 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -144,6 +144,25 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
{
exit_handle_fn exit_handler;
+ if (ARM_ABORT_PENDING(exception_index)) {
+ u8 hsr_ec = kvm_vcpu_trap_get_class(vcpu);
+
+ /*
+ * HVC/SMC already have an adjusted PC, which we need
+ * to correct in order to return to after having
+ * injected the abort.
+ */
+ if (hsr_ec == HSR_EC_HVC || hsr_ec == HSR_EC_SMC) {
+ u32 adj = kvm_vcpu_trap_il_is32bit(vcpu) ? 4 : 2;
+ *vcpu_pc(vcpu) -= adj;
+ }
+
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
+ exception_index = ARM_EXCEPTION_CODE(exception_index);
+
switch (exception_index) {
case ARM_EXCEPTION_IRQ:
return 1;
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 16/19] arm: KVM: Drop unreachable HYP abort handlers
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
Both data and prefetch aborts occuring in HYP lead to a well
deserved panic. Let's get rid of these silly handlers.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 27 ---------------------------
1 file changed, 27 deletions(-)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 4eacb5c..4e40d19 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -28,14 +28,6 @@
typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
-static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* SVC called from Hyp mode should never get here */
- kvm_debug("SVC called from Hyp mode shouldn't go here\n");
- BUG();
- return -EINVAL; /* Squash warning */
-}
-
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
int ret;
@@ -59,22 +51,6 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
return 1;
}
-static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* The hypervisor should never cause aborts */
- kvm_err("Prefetch Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
- kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
- return -EFAULT;
-}
-
-static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* This is either an error in the ws. code or an external abort */
- kvm_err("Data Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
- kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
- return -EFAULT;
-}
-
/**
* kvm_handle_wfx - handle a WFI or WFE instructions trapped in guests
* @vcpu: the vcpu pointer
@@ -112,13 +88,10 @@ static exit_handle_fn arm_exit_handlers[] = {
[HSR_EC_CP14_64] = kvm_handle_cp14_access,
[HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access,
[HSR_EC_CP10_ID] = kvm_handle_cp10_id,
- [HSR_EC_SVC_HYP] = handle_svc_hyp,
[HSR_EC_HVC] = handle_hvc,
[HSR_EC_SMC] = handle_smc,
[HSR_EC_IABT] = kvm_handle_guest_abort,
- [HSR_EC_IABT_HYP] = handle_pabt_hyp,
[HSR_EC_DABT] = kvm_handle_guest_abort,
- [HSR_EC_DABT_HYP] = handle_dabt_hyp,
};
static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 16/19] arm: KVM: Drop unreachable HYP abort handlers
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
Both data and prefetch aborts occuring in HYP lead to a well
deserved panic. Let's get rid of these silly handlers.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/handle_exit.c | 27 ---------------------------
1 file changed, 27 deletions(-)
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 4eacb5c..4e40d19 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -28,14 +28,6 @@
typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);
-static int handle_svc_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* SVC called from Hyp mode should never get here */
- kvm_debug("SVC called from Hyp mode shouldn't go here\n");
- BUG();
- return -EINVAL; /* Squash warning */
-}
-
static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
int ret;
@@ -59,22 +51,6 @@ static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
return 1;
}
-static int handle_pabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* The hypervisor should never cause aborts */
- kvm_err("Prefetch Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
- kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
- return -EFAULT;
-}
-
-static int handle_dabt_hyp(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- /* This is either an error in the ws. code or an external abort */
- kvm_err("Data Abort taken from Hyp mode at %#08lx (HSR: %#08x)\n",
- kvm_vcpu_get_hfar(vcpu), kvm_vcpu_get_hsr(vcpu));
- return -EFAULT;
-}
-
/**
* kvm_handle_wfx - handle a WFI or WFE instructions trapped in guests
* @vcpu: the vcpu pointer
@@ -112,13 +88,10 @@ static exit_handle_fn arm_exit_handlers[] = {
[HSR_EC_CP14_64] = kvm_handle_cp14_access,
[HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access,
[HSR_EC_CP10_ID] = kvm_handle_cp10_id,
- [HSR_EC_SVC_HYP] = handle_svc_hyp,
[HSR_EC_HVC] = handle_hvc,
[HSR_EC_SMC] = handle_smc,
[HSR_EC_IABT] = kvm_handle_guest_abort,
- [HSR_EC_IABT_HYP] = handle_pabt_hyp,
[HSR_EC_DABT] = kvm_handle_guest_abort,
- [HSR_EC_DABT_HYP] = handle_dabt_hyp,
};
static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 17/19] arm/arm64: KVM: Inject virtual abort when guest exits on external abort
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If we spot a data abort bearing the ESR_EL2.EA bit set, we know that
this is an external abort, and that should be punished by a the injection
of an abort.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/mmu.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index bda27b6..6827b54 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1434,6 +1434,11 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
int ret, idx;
is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+ if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) {
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 17/19] arm/arm64: KVM: Inject virtual abort when guest exits on external abort
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If we spot a data abort bearing the ESR_EL2.EA bit set, we know that
this is an external abort, and that should be punished by a the injection
of an abort.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/mmu.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index bda27b6..6827b54 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -1434,6 +1434,11 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
int ret, idx;
is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+ if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) {
+ kvm_inject_vabt(vcpu);
+ return 1;
+ }
+
fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 18/19] arm/arm64: KVM: Remove external abort test from MMIO handling
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
As we know handle external aborts pretty early, we can get rid of
its handling in the MMIO code (which was a bit odd to begin with...).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/mmio.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 10f80a6..b6e715f 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -126,12 +126,6 @@ static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len)
int access_size;
bool sign_extend;
- if (kvm_vcpu_dabt_isextabt(vcpu)) {
- /* cache operation on I/O addr, tell guest unsupported */
- kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
- return 1;
- }
-
if (kvm_vcpu_dabt_iss1tw(vcpu)) {
/* page table accesses IO mem: tell guest to fix its TTBR */
kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 18/19] arm/arm64: KVM: Remove external abort test from MMIO handling
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
As we know handle external aborts pretty early, we can get rid of
its handling in the MMIO code (which was a bit odd to begin with...).
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/kvm/mmio.c | 6 ------
1 file changed, 6 deletions(-)
diff --git a/arch/arm/kvm/mmio.c b/arch/arm/kvm/mmio.c
index 10f80a6..b6e715f 100644
--- a/arch/arm/kvm/mmio.c
+++ b/arch/arm/kvm/mmio.c
@@ -126,12 +126,6 @@ static int decode_hsr(struct kvm_vcpu *vcpu, bool *is_write, int *len)
int access_size;
bool sign_extend;
- if (kvm_vcpu_dabt_isextabt(vcpu)) {
- /* cache operation on I/O addr, tell guest unsupported */
- kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
- return 1;
- }
-
if (kvm_vcpu_dabt_iss1tw(vcpu)) {
/* page table accesses IO mem: tell guest to fix its TTBR */
kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu));
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 19/19] arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-06 13:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
If, when proxying a GICV access at EL2, we detect that the guest is
doing something silly, report an EL1 SError instead ofgnoring the
access.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_hyp.h | 2 +-
arch/arm64/kvm/hyp/switch.c | 18 +++++++++++++++---
virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++++++-----
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 88ec3ac..b18e852 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -123,7 +123,7 @@ typeof(orig) * __hyp_text fname(void) \
void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
-bool __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
+int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 1233a55..194184c 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -311,9 +311,21 @@ again:
!kvm_vcpu_dabt_isextabt(vcpu) &&
!kvm_vcpu_dabt_iss1tw(vcpu);
- if (valid && __vgic_v2_perform_cpuif_access(vcpu)) {
- __skip_instr(vcpu);
- goto again;
+ if (valid) {
+ int ret = __vgic_v2_perform_cpuif_access(vcpu);
+
+ if (ret == 1) {
+ __skip_instr(vcpu);
+ goto again;
+ }
+
+ if (ret == -1) {
+ /* Promote an illegal access to an SError */
+ __skip_instr(vcpu);
+ exit_code = ARM_EXCEPTION_EL1_SERROR;
+ }
+
+ /* 0 falls through to be handler out of EL2 */
}
}
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index a052f20..c8aeb7b 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -170,7 +170,18 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
}
#ifdef CONFIG_ARM64
-bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
+/*
+ * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
+ * guest.
+ *
+ * @vcpu: the offending vcpu
+ *
+ * Returns:
+ * 1: GICV access successfully performed
+ * 0: Not a GICV access
+ * -1: Illegal GICV access
+ */
+int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
struct vgic_dist *vgic = &kvm->arch.vgic;
@@ -185,15 +196,15 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
/* If not for GICV, move on */
if (fault_ipa < vgic->vgic_cpu_base ||
fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
- return false;
+ return 0;
/* Reject anything but a 32bit access */
if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32))
- return false;
+ return -1;
/* Not aligned? Don't bother */
if (fault_ipa & 3)
- return false;
+ return -1;
rd = kvm_vcpu_dabt_get_rd(vcpu);
addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va);
@@ -210,6 +221,6 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
sizeof(u32)));
}
- return true;
+ return 1;
}
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* [PATCH 19/19] arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
@ 2016-09-06 13:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-06 13:02 UTC (permalink / raw)
To: linux-arm-kernel
If, when proxying a GICV access at EL2, we detect that the guest is
doing something silly, report an EL1 SError instead ofgnoring the
access.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm64/include/asm/kvm_hyp.h | 2 +-
arch/arm64/kvm/hyp/switch.c | 18 +++++++++++++++---
virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++++++-----
3 files changed, 32 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index 88ec3ac..b18e852 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -123,7 +123,7 @@ typeof(orig) * __hyp_text fname(void) \
void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
-bool __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
+int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index 1233a55..194184c 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -311,9 +311,21 @@ again:
!kvm_vcpu_dabt_isextabt(vcpu) &&
!kvm_vcpu_dabt_iss1tw(vcpu);
- if (valid && __vgic_v2_perform_cpuif_access(vcpu)) {
- __skip_instr(vcpu);
- goto again;
+ if (valid) {
+ int ret = __vgic_v2_perform_cpuif_access(vcpu);
+
+ if (ret == 1) {
+ __skip_instr(vcpu);
+ goto again;
+ }
+
+ if (ret == -1) {
+ /* Promote an illegal access to an SError */
+ __skip_instr(vcpu);
+ exit_code = ARM_EXCEPTION_EL1_SERROR;
+ }
+
+ /* 0 falls through to be handler out of EL2 */
}
}
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index a052f20..c8aeb7b 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -170,7 +170,18 @@ void __hyp_text __vgic_v2_restore_state(struct kvm_vcpu *vcpu)
}
#ifdef CONFIG_ARM64
-bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
+/*
+ * __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
+ * guest.
+ *
+ * @vcpu: the offending vcpu
+ *
+ * Returns:
+ * 1: GICV access successfully performed
+ * 0: Not a GICV access
+ * -1: Illegal GICV access
+ */
+int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
{
struct kvm *kvm = kern_hyp_va(vcpu->kvm);
struct vgic_dist *vgic = &kvm->arch.vgic;
@@ -185,15 +196,15 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
/* If not for GICV, move on */
if (fault_ipa < vgic->vgic_cpu_base ||
fault_ipa >= (vgic->vgic_cpu_base + KVM_VGIC_V2_CPU_SIZE))
- return false;
+ return 0;
/* Reject anything but a 32bit access */
if (kvm_vcpu_dabt_get_as(vcpu) != sizeof(u32))
- return false;
+ return -1;
/* Not aligned? Don't bother */
if (fault_ipa & 3)
- return false;
+ return -1;
rd = kvm_vcpu_dabt_get_rd(vcpu);
addr = kern_hyp_va((kern_hyp_va(&kvm_vgic_global_state))->vcpu_base_va);
@@ -210,6 +221,6 @@ bool __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
sizeof(u32)));
}
- return true;
+ return 1;
}
#endif
--
2.1.4
^ permalink raw reply related [flat|nested] 56+ messages in thread
* Re: [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
2016-09-06 13:02 ` Marc Zyngier
@ 2016-09-07 17:03 ` Christoffer Dall
-1 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-07 17:03 UTC (permalink / raw)
To: Marc Zyngier; +Cc: kvm, linux-arm-kernel, kvmarm
On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
> If EL1 generates an asynchronous abort and then traps into EL2
> before the abort has been delivered, we may end-up with the
> abort firing at the worse possible place: on the host.
>
> In order to avoid this, it is necessary to take the abort at EL2,
> by clearing the PSTATE.A bit. In order to survive this abort,
> we do it at a point where we're in a known state with respect
> to the world switch, and handle the resulting exception,
> overloading the exit code in the process.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
> arch/arm64/kvm/hyp/switch.c | 6 ++++++
> 3 files changed, 61 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> index 3967c231..7662ef5 100644
> --- a/arch/arm64/kvm/hyp/entry.S
> +++ b/arch/arm64/kvm/hyp/entry.S
> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
> // Now restore the host regs
> restore_callee_saved_regs x2
>
> - ret
> + // If we have a pending asynchronous abort, now is the
> + // time to find out. From your VAXorcist book, page 666:
> + // "Threaten me not, oh Evil one! For I speak with
> + // the power of DEC, and I command thee to show thyself!"
> + mrs x2, elr_el2
> + mrs x3, esr_el2
> + mrs x4, spsr_el2
> + mov x5, x0
> +
> + dsb sy // Synchronize against in-flight ld/st
> + msr daifclr, #4 // Unmask aborts
> +
> + // This is our single instruction exception window. A pending
> + // SError is guaranteed to occur at the earliest when we unmask
> + // it, and at the latest just after the ISB.
Why is it guaranteed to to occur at the latest after the ISB? I thought
that asynchronous exceptions could in theory be deferred until forever,
but I am probably wrong about this.
Otherwise, this looks good!
-Christoffer
> + .global abort_guest_exit_start
> +abort_guest_exit_start:
> +
> + isb
> +
> + .global abort_guest_exit_end
> +abort_guest_exit_end:
> +
> + // If the exception took place, restore the EL1 exception
> + // context so that we can report some information.
> + // Merge the exception code with the SError pending bit.
> + tbz x0, #ARM_EXIT_WITH_SERROR_BIT, 1f
> + msr elr_el2, x2
> + msr esr_el2, x3
> + msr spsr_el2, x4
> + orr x0, x0, x5
> +1: ret
> ENDPROC(__guest_exit)
>
> ENTRY(__fpsimd_guest_restore)
> diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> index d2f6640..4e92399 100644
> --- a/arch/arm64/kvm/hyp/hyp-entry.S
> +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> @@ -126,6 +126,28 @@ el1_error:
> mov x0, #ARM_EXCEPTION_EL1_SERROR
> b __guest_exit
>
> +el2_error:
> + /*
> + * Only two possibilities:
> + * 1) Either we come from the exit path, having just unmasked
> + * PSTATE.A: change the return code to an EL2 fault, and
> + * carry on, as we're already in a sane state to handle it.
> + * 2) Or we come from anywhere else, and that's a bug: we panic.
> + *
> + * For (1), x0 contains the original return code and x1 doesn't
> + * contain anything meaningful at that stage. We can reuse them
> + * as temp registers.
> + * For (2), who cares?
> + */
> + mrs x0, elr_el2
> + adr x1, abort_guest_exit_start
> + cmp x0, x1
> + adr x1, abort_guest_exit_end
> + ccmp x0, x1, #4, ne
> + b.ne __hyp_panic
> + mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
> + eret
> +
> ENTRY(__hyp_do_panic)
> mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
> PSR_MODE_EL1h)
> @@ -150,7 +172,6 @@ ENDPROC(\label)
> invalid_vector el2h_sync_invalid
> invalid_vector el2h_irq_invalid
> invalid_vector el2h_fiq_invalid
> - invalid_vector el2h_error_invalid
> invalid_vector el1_sync_invalid
> invalid_vector el1_irq_invalid
> invalid_vector el1_fiq_invalid
> @@ -168,7 +189,7 @@ ENTRY(__kvm_hyp_vector)
> ventry el2h_sync_invalid // Synchronous EL2h
> ventry el2h_irq_invalid // IRQ EL2h
> ventry el2h_fiq_invalid // FIQ EL2h
> - ventry el2h_error_invalid // Error EL2h
> + ventry el2_error // Error EL2h
>
> ventry el1_sync // Synchronous 64-bit EL1
> ventry el1_irq // IRQ 64-bit EL1
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 5148b06..1233a55 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -292,6 +292,12 @@ again:
> exit_code = __guest_enter(vcpu, host_ctxt);
> /* And we're baaack! */
>
> + /*
> + * We're using the raw exception code in order to only process
> + * the trap if no SError is pending. We will come back to the
> + * same PC once the SError has been injected, and replay the
> + * trapping instruction.
> + */
> if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
> goto again;
>
> --
> 2.1.4
>
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
@ 2016-09-07 17:03 ` Christoffer Dall
0 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-07 17:03 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
> If EL1 generates an asynchronous abort and then traps into EL2
> before the abort has been delivered, we may end-up with the
> abort firing at the worse possible place: on the host.
>
> In order to avoid this, it is necessary to take the abort at EL2,
> by clearing the PSTATE.A bit. In order to survive this abort,
> we do it at a point where we're in a known state with respect
> to the world switch, and handle the resulting exception,
> overloading the exit code in the process.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
> arch/arm64/kvm/hyp/switch.c | 6 ++++++
> 3 files changed, 61 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> index 3967c231..7662ef5 100644
> --- a/arch/arm64/kvm/hyp/entry.S
> +++ b/arch/arm64/kvm/hyp/entry.S
> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
> // Now restore the host regs
> restore_callee_saved_regs x2
>
> - ret
> + // If we have a pending asynchronous abort, now is the
> + // time to find out. From your VAXorcist book, page 666:
> + // "Threaten me not, oh Evil one! For I speak with
> + // the power of DEC, and I command thee to show thyself!"
> + mrs x2, elr_el2
> + mrs x3, esr_el2
> + mrs x4, spsr_el2
> + mov x5, x0
> +
> + dsb sy // Synchronize against in-flight ld/st
> + msr daifclr, #4 // Unmask aborts
> +
> + // This is our single instruction exception window. A pending
> + // SError is guaranteed to occur at the earliest when we unmask
> + // it, and at the latest just after the ISB.
Why is it guaranteed to to occur at the latest after the ISB? I thought
that asynchronous exceptions could in theory be deferred until forever,
but I am probably wrong about this.
Otherwise, this looks good!
-Christoffer
> + .global abort_guest_exit_start
> +abort_guest_exit_start:
> +
> + isb
> +
> + .global abort_guest_exit_end
> +abort_guest_exit_end:
> +
> + // If the exception took place, restore the EL1 exception
> + // context so that we can report some information.
> + // Merge the exception code with the SError pending bit.
> + tbz x0, #ARM_EXIT_WITH_SERROR_BIT, 1f
> + msr elr_el2, x2
> + msr esr_el2, x3
> + msr spsr_el2, x4
> + orr x0, x0, x5
> +1: ret
> ENDPROC(__guest_exit)
>
> ENTRY(__fpsimd_guest_restore)
> diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S
> index d2f6640..4e92399 100644
> --- a/arch/arm64/kvm/hyp/hyp-entry.S
> +++ b/arch/arm64/kvm/hyp/hyp-entry.S
> @@ -126,6 +126,28 @@ el1_error:
> mov x0, #ARM_EXCEPTION_EL1_SERROR
> b __guest_exit
>
> +el2_error:
> + /*
> + * Only two possibilities:
> + * 1) Either we come from the exit path, having just unmasked
> + * PSTATE.A: change the return code to an EL2 fault, and
> + * carry on, as we're already in a sane state to handle it.
> + * 2) Or we come from anywhere else, and that's a bug: we panic.
> + *
> + * For (1), x0 contains the original return code and x1 doesn't
> + * contain anything meaningful at that stage. We can reuse them
> + * as temp registers.
> + * For (2), who cares?
> + */
> + mrs x0, elr_el2
> + adr x1, abort_guest_exit_start
> + cmp x0, x1
> + adr x1, abort_guest_exit_end
> + ccmp x0, x1, #4, ne
> + b.ne __hyp_panic
> + mov x0, #(1 << ARM_EXIT_WITH_SERROR_BIT)
> + eret
> +
> ENTRY(__hyp_do_panic)
> mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
> PSR_MODE_EL1h)
> @@ -150,7 +172,6 @@ ENDPROC(\label)
> invalid_vector el2h_sync_invalid
> invalid_vector el2h_irq_invalid
> invalid_vector el2h_fiq_invalid
> - invalid_vector el2h_error_invalid
> invalid_vector el1_sync_invalid
> invalid_vector el1_irq_invalid
> invalid_vector el1_fiq_invalid
> @@ -168,7 +189,7 @@ ENTRY(__kvm_hyp_vector)
> ventry el2h_sync_invalid // Synchronous EL2h
> ventry el2h_irq_invalid // IRQ EL2h
> ventry el2h_fiq_invalid // FIQ EL2h
> - ventry el2h_error_invalid // Error EL2h
> + ventry el2_error // Error EL2h
>
> ventry el1_sync // Synchronous 64-bit EL1
> ventry el1_irq // IRQ 64-bit EL1
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index 5148b06..1233a55 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -292,6 +292,12 @@ again:
> exit_code = __guest_enter(vcpu, host_ctxt);
> /* And we're baaack! */
>
> + /*
> + * We're using the raw exception code in order to only process
> + * the trap if no SError is pending. We will come back to the
> + * same PC once the SError has been injected, and replay the
> + * trapping instruction.
> + */
> if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu))
> goto again;
>
> --
> 2.1.4
>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
2016-09-07 17:03 ` Christoffer Dall
@ 2016-09-07 17:21 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-07 17:21 UTC (permalink / raw)
To: Christoffer Dall; +Cc: kvm, linux-arm-kernel, kvmarm
On 07/09/16 18:03, Christoffer Dall wrote:
> On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
>> If EL1 generates an asynchronous abort and then traps into EL2
>> before the abort has been delivered, we may end-up with the
>> abort firing at the worse possible place: on the host.
>>
>> In order to avoid this, it is necessary to take the abort at EL2,
>> by clearing the PSTATE.A bit. In order to survive this abort,
>> we do it at a point where we're in a known state with respect
>> to the world switch, and handle the resulting exception,
>> overloading the exit code in the process.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
>> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
>> arch/arm64/kvm/hyp/switch.c | 6 ++++++
>> 3 files changed, 61 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
>> index 3967c231..7662ef5 100644
>> --- a/arch/arm64/kvm/hyp/entry.S
>> +++ b/arch/arm64/kvm/hyp/entry.S
>> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
>> // Now restore the host regs
>> restore_callee_saved_regs x2
>>
>> - ret
>> + // If we have a pending asynchronous abort, now is the
>> + // time to find out. From your VAXorcist book, page 666:
>> + // "Threaten me not, oh Evil one! For I speak with
>> + // the power of DEC, and I command thee to show thyself!"
>> + mrs x2, elr_el2
>> + mrs x3, esr_el2
>> + mrs x4, spsr_el2
>> + mov x5, x0
>> +
>> + dsb sy // Synchronize against in-flight ld/st
>> + msr daifclr, #4 // Unmask aborts
>> +
>> + // This is our single instruction exception window. A pending
>> + // SError is guaranteed to occur at the earliest when we unmask
>> + // it, and at the latest just after the ISB.
>
> Why is it guaranteed to to occur at the latest after the ISB? I thought
> that asynchronous exceptions could in theory be deferred until forever,
> but I am probably wrong about this.
The DSB is going to force all transactions to be completed and at that
point, we shouldn't have anything being further delayed (this is not an
architectural guarantee, but something that happens to work on the cores
I have access to), and the potential exception becomes pending.
At this point, we perform the unmask. A pending exception *can* fire at
that point, but is not guaranteed to do so. But the ISB, being a
"context synchronization event", guarantees that the exception fires
before the first instruction that follows the ISB (see D1.14.4). This is
what gives us this one instruction window (after the unmask, or after
the isb).
Hope this helps,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
@ 2016-09-07 17:21 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-07 17:21 UTC (permalink / raw)
To: linux-arm-kernel
On 07/09/16 18:03, Christoffer Dall wrote:
> On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
>> If EL1 generates an asynchronous abort and then traps into EL2
>> before the abort has been delivered, we may end-up with the
>> abort firing at the worse possible place: on the host.
>>
>> In order to avoid this, it is necessary to take the abort at EL2,
>> by clearing the PSTATE.A bit. In order to survive this abort,
>> we do it at a point where we're in a known state with respect
>> to the world switch, and handle the resulting exception,
>> overloading the exit code in the process.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
>> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
>> arch/arm64/kvm/hyp/switch.c | 6 ++++++
>> 3 files changed, 61 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
>> index 3967c231..7662ef5 100644
>> --- a/arch/arm64/kvm/hyp/entry.S
>> +++ b/arch/arm64/kvm/hyp/entry.S
>> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
>> // Now restore the host regs
>> restore_callee_saved_regs x2
>>
>> - ret
>> + // If we have a pending asynchronous abort, now is the
>> + // time to find out. From your VAXorcist book, page 666:
>> + // "Threaten me not, oh Evil one! For I speak with
>> + // the power of DEC, and I command thee to show thyself!"
>> + mrs x2, elr_el2
>> + mrs x3, esr_el2
>> + mrs x4, spsr_el2
>> + mov x5, x0
>> +
>> + dsb sy // Synchronize against in-flight ld/st
>> + msr daifclr, #4 // Unmask aborts
>> +
>> + // This is our single instruction exception window. A pending
>> + // SError is guaranteed to occur at the earliest when we unmask
>> + // it, and at the latest just after the ISB.
>
> Why is it guaranteed to to occur at the latest after the ISB? I thought
> that asynchronous exceptions could in theory be deferred until forever,
> but I am probably wrong about this.
The DSB is going to force all transactions to be completed and at that
point, we shouldn't have anything being further delayed (this is not an
architectural guarantee, but something that happens to work on the cores
I have access to), and the potential exception becomes pending.
At this point, we perform the unmask. A pending exception *can* fire at
that point, but is not guaranteed to do so. But the ISB, being a
"context synchronization event", guarantees that the exception fires
before the first instruction that follows the ISB (see D1.14.4). This is
what gives us this one instruction window (after the unmask, or after
the isb).
Hope this helps,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
2016-09-07 17:21 ` Marc Zyngier
@ 2016-09-08 8:47 ` Christoffer Dall
-1 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 8:47 UTC (permalink / raw)
To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, kvmarm
On Wed, Sep 07, 2016 at 06:21:55PM +0100, Marc Zyngier wrote:
> On 07/09/16 18:03, Christoffer Dall wrote:
> > On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
> >> If EL1 generates an asynchronous abort and then traps into EL2
> >> before the abort has been delivered, we may end-up with the
> >> abort firing at the worse possible place: on the host.
> >>
> >> In order to avoid this, it is necessary to take the abort at EL2,
> >> by clearing the PSTATE.A bit. In order to survive this abort,
> >> we do it at a point where we're in a known state with respect
> >> to the world switch, and handle the resulting exception,
> >> overloading the exit code in the process.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
> >> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
> >> arch/arm64/kvm/hyp/switch.c | 6 ++++++
> >> 3 files changed, 61 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> >> index 3967c231..7662ef5 100644
> >> --- a/arch/arm64/kvm/hyp/entry.S
> >> +++ b/arch/arm64/kvm/hyp/entry.S
> >> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
> >> // Now restore the host regs
> >> restore_callee_saved_regs x2
> >>
> >> - ret
> >> + // If we have a pending asynchronous abort, now is the
> >> + // time to find out. From your VAXorcist book, page 666:
> >> + // "Threaten me not, oh Evil one! For I speak with
> >> + // the power of DEC, and I command thee to show thyself!"
> >> + mrs x2, elr_el2
> >> + mrs x3, esr_el2
> >> + mrs x4, spsr_el2
> >> + mov x5, x0
> >> +
> >> + dsb sy // Synchronize against in-flight ld/st
> >> + msr daifclr, #4 // Unmask aborts
> >> +
> >> + // This is our single instruction exception window. A pending
> >> + // SError is guaranteed to occur at the earliest when we unmask
> >> + // it, and at the latest just after the ISB.
> >
> > Why is it guaranteed to to occur at the latest after the ISB? I thought
> > that asynchronous exceptions could in theory be deferred until forever,
> > but I am probably wrong about this.
>
> The DSB is going to force all transactions to be completed and at that
> point, we shouldn't have anything being further delayed (this is not an
> architectural guarantee, but something that happens to work on the cores
> I have access to), and the potential exception becomes pending.
>
> At this point, we perform the unmask. A pending exception *can* fire at
> that point, but is not guaranteed to do so. But the ISB, being a
> "context synchronization event", guarantees that the exception fires
> before the first instruction that follows the ISB (see D1.14.4). This is
> what gives us this one instruction window (after the unmask, or after
> the isb).
>
Yes, this makes sense. So if by whatever weird sequence of events we
see an SError after the ISB, we simply give up and admit that the system
is screwy, which also makes sense.
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2
@ 2016-09-08 8:47 ` Christoffer Dall
0 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 8:47 UTC (permalink / raw)
To: linux-arm-kernel
On Wed, Sep 07, 2016 at 06:21:55PM +0100, Marc Zyngier wrote:
> On 07/09/16 18:03, Christoffer Dall wrote:
> > On Tue, Sep 06, 2016 at 02:02:07PM +0100, Marc Zyngier wrote:
> >> If EL1 generates an asynchronous abort and then traps into EL2
> >> before the abort has been delivered, we may end-up with the
> >> abort firing at the worse possible place: on the host.
> >>
> >> In order to avoid this, it is necessary to take the abort at EL2,
> >> by clearing the PSTATE.A bit. In order to survive this abort,
> >> we do it at a point where we're in a known state with respect
> >> to the world switch, and handle the resulting exception,
> >> overloading the exit code in the process.
> >>
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >> arch/arm64/kvm/hyp/entry.S | 33 ++++++++++++++++++++++++++++++++-
> >> arch/arm64/kvm/hyp/hyp-entry.S | 25 +++++++++++++++++++++++--
> >> arch/arm64/kvm/hyp/switch.c | 6 ++++++
> >> 3 files changed, 61 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S
> >> index 3967c231..7662ef5 100644
> >> --- a/arch/arm64/kvm/hyp/entry.S
> >> +++ b/arch/arm64/kvm/hyp/entry.S
> >> @@ -122,7 +122,38 @@ ENTRY(__guest_exit)
> >> // Now restore the host regs
> >> restore_callee_saved_regs x2
> >>
> >> - ret
> >> + // If we have a pending asynchronous abort, now is the
> >> + // time to find out. From your VAXorcist book, page 666:
> >> + // "Threaten me not, oh Evil one! For I speak with
> >> + // the power of DEC, and I command thee to show thyself!"
> >> + mrs x2, elr_el2
> >> + mrs x3, esr_el2
> >> + mrs x4, spsr_el2
> >> + mov x5, x0
> >> +
> >> + dsb sy // Synchronize against in-flight ld/st
> >> + msr daifclr, #4 // Unmask aborts
> >> +
> >> + // This is our single instruction exception window. A pending
> >> + // SError is guaranteed to occur at the earliest when we unmask
> >> + // it, and at the latest just after the ISB.
> >
> > Why is it guaranteed to to occur at the latest after the ISB? I thought
> > that asynchronous exceptions could in theory be deferred until forever,
> > but I am probably wrong about this.
>
> The DSB is going to force all transactions to be completed and at that
> point, we shouldn't have anything being further delayed (this is not an
> architectural guarantee, but something that happens to work on the cores
> I have access to), and the potential exception becomes pending.
>
> At this point, we perform the unmask. A pending exception *can* fire at
> that point, but is not guaranteed to do so. But the ISB, being a
> "context synchronization event", guarantees that the exception fires
> before the first instruction that follows the ISB (see D1.14.4). This is
> what gives us this one instruction window (after the unmask, or after
> the isb).
>
Yes, this makes sense. So if by whatever weird sequence of events we
see an SError after the ISB, we simply give up and admit that the system
is screwy, which also makes sense.
Thanks,
-Christoffer
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 17/19] arm/arm64: KVM: Inject virtual abort when guest exits on external abort
2016-09-06 13:02 ` Marc Zyngier
@ 2016-09-08 9:09 ` Christoffer Dall
-1 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 9:09 UTC (permalink / raw)
To: Marc Zyngier; +Cc: kvm, linux-arm-kernel, kvmarm
On Tue, Sep 06, 2016 at 02:02:15PM +0100, Marc Zyngier wrote:
> If we spot a data abort bearing the ESR_EL2.EA bit set, we know that
> this is an external abort, and that should be punished by a the injection
nit: s/a//
(I can fix this up though)
> of an abort.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm/kvm/mmu.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index bda27b6..6827b54 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -1434,6 +1434,11 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
> int ret, idx;
>
> is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
> + if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) {
> + kvm_inject_vabt(vcpu);
> + return 1;
> + }
> +
> fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
>
> trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
> --
> 2.1.4
>
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 17/19] arm/arm64: KVM: Inject virtual abort when guest exits on external abort
@ 2016-09-08 9:09 ` Christoffer Dall
0 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 9:09 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Sep 06, 2016 at 02:02:15PM +0100, Marc Zyngier wrote:
> If we spot a data abort bearing the ESR_EL2.EA bit set, we know that
> this is an external abort, and that should be punished by a the injection
nit: s/a//
(I can fix this up though)
> of an abort.
>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
> arch/arm/kvm/mmu.c | 5 +++++
> 1 file changed, 5 insertions(+)
>
> diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
> index bda27b6..6827b54 100644
> --- a/arch/arm/kvm/mmu.c
> +++ b/arch/arm/kvm/mmu.c
> @@ -1434,6 +1434,11 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run)
> int ret, idx;
>
> is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
> + if (unlikely(!is_iabt && kvm_vcpu_dabt_isextabt(vcpu))) {
> + kvm_inject_vabt(vcpu);
> + return 1;
> + }
> +
> fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
>
> trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu),
> --
> 2.1.4
>
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 00/19] Handle guest-generated SErrors/Aborts
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-08 9:44 ` Christoffer Dall
-1 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 9:44 UTC (permalink / raw)
To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, kvmarm
On Tue, Sep 06, 2016 at 02:01:58PM +0100, Marc Zyngier wrote:
> A little known "feature" of giving guest access to real memory mapped
> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
> the guest accesses it in a non-conventional way (and depending on how
> HW and firmware have been integrated). So far, KVM lacks any support
> to handle this gracefully.
>
> This series introduces a set of mechanisms to catch such a fault and
> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>
> These aborts can either trigger at EL1 (whilst the guest is running),
> or at EL2 (during the handling of an exit). The first case is pretty
> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
> on arm), but the second one is a bit more fiddly, as we need to ensure
> that the exception is pending by the time we unmask it. This is
> achived by using some heavy DSBs on the hot path, with the following
> caveats:
>
> - I've only been able to trigger the EL2 handling on A57 (Seatle,
> Juno).
> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
> measured the impact on bigger systems
>
> The last patch of this series adds a missing feature to the
> GICV-proxying series, delivering a vSError to a guest that performed
> an illegal access to the GIC.
>
> Patches on top of current kvmarm/queue + the GICV przying series.
przying? proxying? Or something in Polish perhaps?
For the series:
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Applied, thanks.
-Christoffer
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-08 9:44 ` Christoffer Dall
0 siblings, 0 replies; 56+ messages in thread
From: Christoffer Dall @ 2016-09-08 9:44 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Sep 06, 2016 at 02:01:58PM +0100, Marc Zyngier wrote:
> A little known "feature" of giving guest access to real memory mapped
> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
> the guest accesses it in a non-conventional way (and depending on how
> HW and firmware have been integrated). So far, KVM lacks any support
> to handle this gracefully.
>
> This series introduces a set of mechanisms to catch such a fault and
> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>
> These aborts can either trigger at EL1 (whilst the guest is running),
> or at EL2 (during the handling of an exit). The first case is pretty
> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
> on arm), but the second one is a bit more fiddly, as we need to ensure
> that the exception is pending by the time we unmask it. This is
> achived by using some heavy DSBs on the hot path, with the following
> caveats:
>
> - I've only been able to trigger the EL2 handling on A57 (Seatle,
> Juno).
> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
> measured the impact on bigger systems
>
> The last patch of this series adds a missing feature to the
> GICV-proxying series, delivering a vSError to a guest that performed
> an illegal access to the GIC.
>
> Patches on top of current kvmarm/queue + the GICV przying series.
przying? proxying? Or something in Polish perhaps?
For the series:
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Applied, thanks.
-Christoffer
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 00/19] Handle guest-generated SErrors/Aborts
2016-09-06 13:01 ` Marc Zyngier
@ 2016-09-08 9:47 ` Wei Chen
-1 siblings, 0 replies; 56+ messages in thread
From: Wei Chen @ 2016-09-08 9:47 UTC (permalink / raw)
To: Marc Zyngier, Christoffer Dall
Cc: kvm, linux-arm-kernel, kvmarm@lists.cs.columbia.edu; julien.grall
Hi Marc,
On 2016/9/6 21:09, Marc Zyngier wrote:
> A little known "feature" of giving guest access to real memory mapped
> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
> the guest accesses it in a non-conventional way (and depending on how
> HW and firmware have been integrated). So far, KVM lacks any support
> to handle this gracefully.
I can reproduce this issue on Seattle board (ARM64), but I can't
reproduce it on FVP (Cortex-A15x2 ARM32). Did you mean that this issue
onlu takes place on ARMv8? Have you ever reproduced this issue on any
ARM32 platform?
Regards,
>
> This series introduces a set of mechanisms to catch such a fault and
> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>
> These aborts can either trigger at EL1 (whilst the guest is running),
> or at EL2 (during the handling of an exit). The first case is pretty
> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
> on arm), but the second one is a bit more fiddly, as we need to ensure
> that the exception is pending by the time we unmask it. This is
> achived by using some heavy DSBs on the hot path, with the following
> caveats:
>
> - I've only been able to trigger the EL2 handling on A57 (Seatle,
> Juno).
> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
> measured the impact on bigger systems
>
> The last patch of this series adds a missing feature to the
> GICV-proxying series, delivering a vSError to a guest that performed
> an illegal access to the GIC.
>
> Patches on top of current kvmarm/queue + the GICV przying series.
>
> Marc Zyngier (19):
> arm64: KVM: Rename HCR_VA to HCR_VSE
> arm64: KVM: Preserve pending vSError in world switch
> arm64: KVM: Add Virtual Abort injection helper
> arm64: KVM: Add exception code to report EL1 asynchronous aborts
> arm64: KVM: Add EL1 async abort handler
> arm64: KVM: Route asynchronous aborts
> arm64: KVM: Allow an exit code to be tagged with an SError
> arm64: KVM: Inject a Virtual SError if it was pending
> arm64: KVM: Handle async aborts delivered while at EL2
> arm: KVM: Preserve pending Virtual Abort in world switch
> arm: KVM: Add Virtual Abort injection helper
> arm: KVM: Add HYP async abort handler
> arm: KVM: Allow an exit code to be tagged with a Virtual Abort
> arm: KVM: Handle async aborts delivered while at HYP
> arm: KVM: Inject a Virtual Abort if it was pending
> arm: KVM: Drop unreachable HYP abort handlers
> arm/arm64: KVM: Inject virtual abort when guest exits on external
> abort
> arm/arm64: KVM: Remove external abort test from MMIO handling
> arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
>
> arch/arm/include/asm/kvm_asm.h | 4 +++
> arch/arm/include/asm/kvm_emulate.h | 1 +
> arch/arm/kvm/emulate.c | 12 +++++++++
> arch/arm/kvm/handle_exit.c | 49 ++++++++++++++++--------------------
> arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++
> arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++-
> arch/arm/kvm/hyp/switch.c | 9 +++++++
> arch/arm/kvm/mmio.c | 6 -----
> arch/arm/kvm/mmu.c | 5 ++++
> arch/arm64/include/asm/kvm_arm.h | 4 +--
> arch/arm64/include/asm/kvm_asm.h | 9 +++++--
> arch/arm64/include/asm/kvm_emulate.h | 1 +
> arch/arm64/include/asm/kvm_hyp.h | 2 +-
> arch/arm64/kvm/handle_exit.c | 23 +++++++++++++++++
> arch/arm64/kvm/hyp/entry.S | 33 +++++++++++++++++++++++-
> arch/arm64/kvm/hyp/hyp-entry.S | 36 ++++++++++++++++++++++----
> arch/arm64/kvm/hyp/switch.c | 33 +++++++++++++++++++++---
> arch/arm64/kvm/inject_fault.c | 12 +++++++++
> virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++----
> 19 files changed, 254 insertions(+), 53 deletions(-)
>
--
Regards,
Wei Chen
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-08 9:47 ` Wei Chen
0 siblings, 0 replies; 56+ messages in thread
From: Wei Chen @ 2016-09-08 9:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi Marc,
On 2016/9/6 21:09, Marc Zyngier wrote:
> A little known "feature" of giving guest access to real memory mapped
> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
> the guest accesses it in a non-conventional way (and depending on how
> HW and firmware have been integrated). So far, KVM lacks any support
> to handle this gracefully.
I can reproduce this issue on Seattle board (ARM64), but I can't
reproduce it on FVP (Cortex-A15x2 ARM32). Did you mean that this issue
onlu takes place on ARMv8? Have you ever reproduced this issue on any
ARM32 platform?
Regards,
>
> This series introduces a set of mechanisms to catch such a fault and
> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>
> These aborts can either trigger at EL1 (whilst the guest is running),
> or at EL2 (during the handling of an exit). The first case is pretty
> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
> on arm), but the second one is a bit more fiddly, as we need to ensure
> that the exception is pending by the time we unmask it. This is
> achived by using some heavy DSBs on the hot path, with the following
> caveats:
>
> - I've only been able to trigger the EL2 handling on A57 (Seatle,
> Juno).
> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
> measured the impact on bigger systems
>
> The last patch of this series adds a missing feature to the
> GICV-proxying series, delivering a vSError to a guest that performed
> an illegal access to the GIC.
>
> Patches on top of current kvmarm/queue + the GICV przying series.
>
> Marc Zyngier (19):
> arm64: KVM: Rename HCR_VA to HCR_VSE
> arm64: KVM: Preserve pending vSError in world switch
> arm64: KVM: Add Virtual Abort injection helper
> arm64: KVM: Add exception code to report EL1 asynchronous aborts
> arm64: KVM: Add EL1 async abort handler
> arm64: KVM: Route asynchronous aborts
> arm64: KVM: Allow an exit code to be tagged with an SError
> arm64: KVM: Inject a Virtual SError if it was pending
> arm64: KVM: Handle async aborts delivered while at EL2
> arm: KVM: Preserve pending Virtual Abort in world switch
> arm: KVM: Add Virtual Abort injection helper
> arm: KVM: Add HYP async abort handler
> arm: KVM: Allow an exit code to be tagged with a Virtual Abort
> arm: KVM: Handle async aborts delivered while at HYP
> arm: KVM: Inject a Virtual Abort if it was pending
> arm: KVM: Drop unreachable HYP abort handlers
> arm/arm64: KVM: Inject virtual abort when guest exits on external
> abort
> arm/arm64: KVM: Remove external abort test from MMIO handling
> arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2
>
> arch/arm/include/asm/kvm_asm.h | 4 +++
> arch/arm/include/asm/kvm_emulate.h | 1 +
> arch/arm/kvm/emulate.c | 12 +++++++++
> arch/arm/kvm/handle_exit.c | 49 ++++++++++++++++--------------------
> arch/arm/kvm/hyp/entry.S | 31 +++++++++++++++++++++++
> arch/arm/kvm/hyp/hyp-entry.S | 16 +++++++++++-
> arch/arm/kvm/hyp/switch.c | 9 +++++++
> arch/arm/kvm/mmio.c | 6 -----
> arch/arm/kvm/mmu.c | 5 ++++
> arch/arm64/include/asm/kvm_arm.h | 4 +--
> arch/arm64/include/asm/kvm_asm.h | 9 +++++--
> arch/arm64/include/asm/kvm_emulate.h | 1 +
> arch/arm64/include/asm/kvm_hyp.h | 2 +-
> arch/arm64/kvm/handle_exit.c | 23 +++++++++++++++++
> arch/arm64/kvm/hyp/entry.S | 33 +++++++++++++++++++++++-
> arch/arm64/kvm/hyp/hyp-entry.S | 36 ++++++++++++++++++++++----
> arch/arm64/kvm/hyp/switch.c | 33 +++++++++++++++++++++---
> arch/arm64/kvm/inject_fault.c | 12 +++++++++
> virt/kvm/arm/hyp/vgic-v2-sr.c | 21 ++++++++++++----
> 19 files changed, 254 insertions(+), 53 deletions(-)
>
--
Regards,
Wei Chen
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 00/19] Handle guest-generated SErrors/Aborts
2016-09-08 9:44 ` Christoffer Dall
@ 2016-09-08 9:55 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-08 9:55 UTC (permalink / raw)
To: Christoffer Dall; +Cc: linux-arm-kernel, kvm, kvmarm
On 08/09/16 10:44, Christoffer Dall wrote:
> On Tue, Sep 06, 2016 at 02:01:58PM +0100, Marc Zyngier wrote:
>> A little known "feature" of giving guest access to real memory mapped
>> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
>> the guest accesses it in a non-conventional way (and depending on how
>> HW and firmware have been integrated). So far, KVM lacks any support
>> to handle this gracefully.
>>
>> This series introduces a set of mechanisms to catch such a fault and
>> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>>
>> These aborts can either trigger at EL1 (whilst the guest is running),
>> or at EL2 (during the handling of an exit). The first case is pretty
>> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
>> on arm), but the second one is a bit more fiddly, as we need to ensure
>> that the exception is pending by the time we unmask it. This is
>> achived by using some heavy DSBs on the hot path, with the following
>> caveats:
>>
>> - I've only been able to trigger the EL2 handling on A57 (Seatle,
>> Juno).
>> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
>> measured the impact on bigger systems
>>
>> The last patch of this series adds a missing feature to the
>> GICV-proxying series, delivering a vSError to a guest that performed
>> an illegal access to the GIC.
>>
>> Patches on top of current kvmarm/queue + the GICV przying series.
>
> przying? proxying? Or something in Polish perhaps?
Proxying, with added fat fingers... ;-)
>
> For the series:
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Thanks!
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-08 9:55 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-08 9:55 UTC (permalink / raw)
To: linux-arm-kernel
On 08/09/16 10:44, Christoffer Dall wrote:
> On Tue, Sep 06, 2016 at 02:01:58PM +0100, Marc Zyngier wrote:
>> A little known "feature" of giving guest access to real memory mapped
>> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
>> the guest accesses it in a non-conventional way (and depending on how
>> HW and firmware have been integrated). So far, KVM lacks any support
>> to handle this gracefully.
>>
>> This series introduces a set of mechanisms to catch such a fault and
>> deliver a vSError (or Virtual Abort for 32bit) to the offending vcpu.
>>
>> These aborts can either trigger at EL1 (whilst the guest is running),
>> or at EL2 (during the handling of an exit). The first case is pretty
>> easy to handle (use the ad-hoc vectors on arm64, or decode the EA bit
>> on arm), but the second one is a bit more fiddly, as we need to ensure
>> that the exception is pending by the time we unmask it. This is
>> achived by using some heavy DSBs on the hot path, with the following
>> caveats:
>>
>> - I've only been able to trigger the EL2 handling on A57 (Seatle,
>> Juno).
>> - I've measured a 40/50 cycles hit on Juno (A57), but I haven't
>> measured the impact on bigger systems
>>
>> The last patch of this series adds a missing feature to the
>> GICV-proxying series, delivering a vSError to a guest that performed
>> an illegal access to the GIC.
>>
>> Patches on top of current kvmarm/queue + the GICV przying series.
>
> przying? proxying? Or something in Polish perhaps?
Proxying, with added fat fingers... ;-)
>
> For the series:
> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Thanks!
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
* Re: [PATCH 00/19] Handle guest-generated SErrors/Aborts
2016-09-08 9:47 ` Wei Chen
@ 2016-09-08 10:02 ` Marc Zyngier
-1 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-08 10:02 UTC (permalink / raw)
To: Wei Chen, Christoffer Dall
Cc: kvm, linux-arm-kernel, kvmarm@lists.cs.columbia.edu; julien.grall
Hi Wei,
On 08/09/16 10:47, Wei Chen wrote:
> Hi Marc,
>
> On 2016/9/6 21:09, Marc Zyngier wrote:
>> A little known "feature" of giving guest access to real memory mapped
>> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
>> the guest accesses it in a non-conventional way (and depending on how
>> HW and firmware have been integrated). So far, KVM lacks any support
>> to handle this gracefully.
>
> I can reproduce this issue on Seattle board (ARM64), but I can't
> reproduce it on FVP (Cortex-A15x2 ARM32). Did you mean that this issue
> onlu takes place on ARMv8? Have you ever reproduced this issue on any
> ARM32 platform?
On a 32bit platform, I've only managed to get an external abort firing
while running at EL1 and then taken to HYP. But that doesn't mean that
32bit systems are immune to this. It completely depends on the system
integration (how fast the error generating peripheral replies and how
the error is exposed to the CPU, for example).
As for the model, I'd be surprised if it had any facility for this. Most
of that is IMPDEF, and ignoring the error seems to be a valid
implementation...
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
* [PATCH 00/19] Handle guest-generated SErrors/Aborts
@ 2016-09-08 10:02 ` Marc Zyngier
0 siblings, 0 replies; 56+ messages in thread
From: Marc Zyngier @ 2016-09-08 10:02 UTC (permalink / raw)
To: linux-arm-kernel
Hi Wei,
On 08/09/16 10:47, Wei Chen wrote:
> Hi Marc,
>
> On 2016/9/6 21:09, Marc Zyngier wrote:
>> A little known "feature" of giving guest access to real memory mapped
>> HW is that it could trigger asynchronous aborts (SError on ARMv8) if
>> the guest accesses it in a non-conventional way (and depending on how
>> HW and firmware have been integrated). So far, KVM lacks any support
>> to handle this gracefully.
>
> I can reproduce this issue on Seattle board (ARM64), but I can't
> reproduce it on FVP (Cortex-A15x2 ARM32). Did you mean that this issue
> onlu takes place on ARMv8? Have you ever reproduced this issue on any
> ARM32 platform?
On a 32bit platform, I've only managed to get an external abort firing
while running at EL1 and then taken to HYP. But that doesn't mean that
32bit systems are immune to this. It completely depends on the system
integration (how fast the error generating peripheral replies and how
the error is exposed to the CPU, for example).
As for the model, I'd be surprised if it had any facility for this. Most
of that is IMPDEF, and ignoring the error seems to be a valid
implementation...
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 56+ messages in thread
end of thread, other threads:[~2016-09-08 10:02 UTC | newest]
Thread overview: 56+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-06 13:01 [PATCH 00/19] Handle guest-generated SErrors/Aborts Marc Zyngier
2016-09-06 13:01 ` Marc Zyngier
2016-09-06 13:01 ` [PATCH 01/19] arm64: KVM: Rename HCR_VA to HCR_VSE Marc Zyngier
2016-09-06 13:01 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 02/19] arm64: KVM: Preserve pending vSError in world switch Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 03/19] arm64: KVM: Add Virtual Abort injection helper Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 04/19] arm64: KVM: Add exception code to report EL1 asynchronous aborts Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 05/19] arm64: KVM: Add EL1 async abort handler Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 06/19] arm64: KVM: Route asynchronous aborts Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 07/19] arm64: KVM: Allow an exit code to be tagged with an SError Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 08/19] arm64: KVM: Inject a Virtual SError if it was pending Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 09/19] arm64: KVM: Handle async aborts delivered while at EL2 Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-07 17:03 ` Christoffer Dall
2016-09-07 17:03 ` Christoffer Dall
2016-09-07 17:21 ` Marc Zyngier
2016-09-07 17:21 ` Marc Zyngier
2016-09-08 8:47 ` Christoffer Dall
2016-09-08 8:47 ` Christoffer Dall
2016-09-06 13:02 ` [PATCH 10/19] arm: KVM: Preserve pending Virtual Abort in world switch Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 11/19] arm: KVM: Add Virtual Abort injection helper Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 12/19] arm: KVM: Add HYP async abort handler Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 13/19] arm: KVM: Allow an exit code to be tagged with a Virtual Abort Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 14/19] arm: KVM: Handle async aborts delivered while at HYP Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 15/19] arm: KVM: Inject a Virtual Abort if it was pending Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 16/19] arm: KVM: Drop unreachable HYP abort handlers Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 17/19] arm/arm64: KVM: Inject virtual abort when guest exits on external abort Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-08 9:09 ` Christoffer Dall
2016-09-08 9:09 ` Christoffer Dall
2016-09-06 13:02 ` [PATCH 18/19] arm/arm64: KVM: Remove external abort test from MMIO handling Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-06 13:02 ` [PATCH 19/19] arm64: KVM: Inject a vSerror if detecting a bad GICV access at EL2 Marc Zyngier
2016-09-06 13:02 ` Marc Zyngier
2016-09-08 9:44 ` [PATCH 00/19] Handle guest-generated SErrors/Aborts Christoffer Dall
2016-09-08 9:44 ` Christoffer Dall
2016-09-08 9:55 ` Marc Zyngier
2016-09-08 9:55 ` Marc Zyngier
2016-09-08 9:47 ` Wei Chen
2016-09-08 9:47 ` Wei Chen
2016-09-08 10:02 ` Marc Zyngier
2016-09-08 10:02 ` Marc Zyngier
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.