[PATCH] KVM: handle the right RAS SEA(Synchronous External Abort) type
When the RAS Extension is implemented, b0b011000, 0b011100, 0b011101, 0b00, and 0b01, are not used and reserved to the DFSC[5:0] of ESR_ELx, but the code still checks these unused bits, so remove them. If the handling of guest ras data error fails, it should inject data instead of SError to let the guest recover as much as possible. CC: Xiang Zheng CC: Xiaofei Tan CC: James Morse Signed-off-by: Dongjiu Geng --- Abort DFSC of ESR_EL2, below web site[1] has clarified: "When the RAS Extension is implemented, 0b011000, 0b011100, 0b011101, 0b00, and 0b01, are reserved." [1]: https://developer.arm.com/docs/ddi0595/b/aarch64-system-registers/esr_el2 --- arch/arm64/include/asm/kvm_emulate.h | 5 - virt/kvm/arm/mmu.c | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index a30b4eec7cb4..857fbc79d678 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -380,11 +380,6 @@ static __always_inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) case FSC_SEA_TTW1: case FSC_SEA_TTW2: case FSC_SEA_TTW3: - case FSC_SECC: - case FSC_SECC_TTW0: - case FSC_SECC_TTW1: - case FSC_SECC_TTW2: - case FSC_SECC_TTW3: return true; default: return false; diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index e3b9ee268823..3c7972ed7fc5 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1926,7 +1926,7 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) return 1; if (unlikely(!is_iabt)) { - kvm_inject_vabt(vcpu); + kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); return 1; } } -- 2.18.0.huawei.25 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[RFC PATCH V2] kvm: arm64: export memory error recovery capability to user space
When user space do memory recovery, it will check whether KVM and guest support the error recovery, only when both of them support, user space will do the error recovery. This patch exports this capability of KVM to user space. Cc: Peter Maydell Signed-off-by: Dongjiu Geng --- v1->v2: 1. check whether host support memory failure instead of RAS capability https://patchwork.kernel.org/patch/10730827/ v1: 1. User space needs to check this capability of host is suggested by Peter[1], this patch as RFC tag because user space patches are still under review, so this kernel patch is firstly sent out for review. [1]: https://patchwork.codeaurora.org/patch/652261/ --- Documentation/virtual/kvm/api.txt | 9 + arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 13 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index cd209f7..822a57b 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4895,3 +4895,12 @@ Architectures: x86 This capability indicates that KVM supports paravirtualized Hyper-V IPI send hypercalls: HvCallSendSyntheticClusterIpi, HvCallSendSyntheticClusterIpiEx. + +8.21 KVM_CAP_ARM_MEMORY_ERROR_RECOVERY + +Architectures: arm, arm64 + +This capability indicates that guest memory error can be detected by the host which +supports the error recovery. When user space do recovery, such as QEMU, it will +check whether host and guest all support memory error recovery, only when both of them +support, user space will do the error recovery. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index b72a3dd..b6e3986 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -84,6 +84,9 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_INJECT_SERROR_ESR: r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); break; + case KVM_CAP_ARM_MEMORY_ERROR_RECOVERY: + r= IS_ENABLED(CONFIG_MEMORY_FAILURE); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 2b7a652..3b19580 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -975,6 +975,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 #define KVM_CAP_EXCEPTION_PAYLOAD 164 #define KVM_CAP_ARM_VM_IPA_SIZE 165 +#define KVM_CAP_ARM_MEMORY_ERROR_RECOVERY 166 #ifdef KVM_CAP_IRQ_ROUTING -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] KVM: arm/arm64: inject an async abort to host if SEA handling failed
If host failed to handle the SEA, KVM should inject an async abort to guest for both SEA data and instruction abort, but it currently only handles the data abort, so correct it. Cc: James Morse Cc: Xiang Zheng Signed-off-by: Dongjiu Geng --- virt/kvm/arm/mmu.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index 27c9583..5882516 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1924,14 +1924,13 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) /* * For RAS the host kernel may handle this abort. * There is no need to pass the error into the guest. +* If host failed to handle it, inject an async abort +* to guest. */ - if (!kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_hsr(vcpu))) - return 1; - - if (unlikely(!is_iabt)) { + if (kvm_handle_guest_sea(fault_ipa, kvm_vcpu_get_hsr(vcpu))) kvm_inject_vabt(vcpu); - return 1; - } + + return 1; } trace_kvm_guest_fault(*vcpu_pc(vcpu), kvm_vcpu_get_hsr(vcpu), -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v4 1/2] arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension()
Rename kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension(), because it does not have any relationship with device. Renaming this function can make code readable. Cc: James Morse Reviewed-by: Suzuki K Poulose Signed-off-by: Dongjiu Geng --- I remeber James also mentioned that rename this function. --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 4 ++-- virt/kvm/arm/arm.c| 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 3ad482d..3ee29db 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -273,7 +273,7 @@ static inline void __cpu_init_stage2(void) kvm_call_hyp(__init_stage2_translation); } -static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { return 0; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3d6d733..c20537f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -53,7 +53,7 @@ int __attribute_const__ kvm_target_cpu(void); int kvm_reset_vcpu(struct kvm_vcpu *vcpu); -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext); +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext); void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start); struct kvm_arch { diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78b..fd37c53 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -55,12 +55,12 @@ static bool cpu_has_32bit_el1(void) } /** - * kvm_arch_dev_ioctl_check_extension + * kvm_arch_vm_ioctl_check_extension * * We currently assume that the number of HW registers is uniform * across all CPUs (see cpuinfo_sanity_check). */ -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index c92053b..40e79ea 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -240,7 +240,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = 1; break; default: - r = kvm_arch_dev_ioctl_check_extension(kvm, ext); + r = kvm_arch_vm_ioctl_check_extension(kvm, ext); break; } return r; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v4 2/2] arm/arm64: KVM: enable 32 bits kvm vcpu events support
The commit 539aee0edb9f ("KVM: arm64: Share the parts of get/set events useful to 32bit") shares the get/set events helper for arm64 and arm32, but forgot to share the cap extension code. User space will check whether KVM supports vcpu events by checking the KVM_CAP_VCPU_EVENTS extension Cc: James Morse Reviewed-by : Suzuki K Poulose Signed-off-by: Dongjiu Geng Acked-by: James Morse --- For the 32 bits kvm migration, it needs to enable the vcpu events, this patch will enable it. The user space QEMU patch is here: https://patchwork.ozlabs.org/patch/975615/ --- arch/arm64/kvm/reset.c | 1 - virt/kvm/arm/arm.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index fd37c53..e50245e 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -82,7 +82,6 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: - case KVM_CAP_VCPU_EVENTS: r = 1; break; default: diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 40e79ea..64e5d97 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -212,6 +212,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: case KVM_CAP_MP_STATE: case KVM_CAP_IMMEDIATE_EXIT: + case KVM_CAP_VCPU_EVENTS: r = 1; break; case KVM_CAP_ARM_SET_DEVICE_ADDR: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v4 0/2] rename function name and enable 32bit vcpu events
Rename the kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension, because the name is not readable; Enable the 32 bit vcpu events support. Change since v3: 1. Address James's comments to update the patch commit messages Change since v2: 1. Address Suzuki's comments to update the patch commit messages change since v1: 1. Update patch commit messages. Dongjiu Geng (2): arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension() arm/arm64: KVM: enable 32 bits kvm vcpu events support arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 5 ++--- virt/kvm/arm/arm.c| 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v3 1/2] arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension()
Rename kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension(), because it does not have any relationship with device. Renaming this function can make code readable. Cc: James Morse Reviewed-by: Suzuki K Poulose Signed-off-by: Dongjiu Geng --- I remeber James also mentioned that rename this function. --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 4 ++-- virt/kvm/arm/arm.c| 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 3ad482d..3ee29db 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -273,7 +273,7 @@ static inline void __cpu_init_stage2(void) kvm_call_hyp(__init_stage2_translation); } -static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { return 0; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3d6d733..c20537f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -53,7 +53,7 @@ int __attribute_const__ kvm_target_cpu(void); int kvm_reset_vcpu(struct kvm_vcpu *vcpu); -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext); +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext); void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start); struct kvm_arch { diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78b..fd37c53 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -55,12 +55,12 @@ static bool cpu_has_32bit_el1(void) } /** - * kvm_arch_dev_ioctl_check_extension + * kvm_arch_vm_ioctl_check_extension * * We currently assume that the number of HW registers is uniform * across all CPUs (see cpuinfo_sanity_check). */ -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index c92053b..40e79ea 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -240,7 +240,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = 1; break; default: - r = kvm_arch_dev_ioctl_check_extension(kvm, ext); + r = kvm_arch_vm_ioctl_check_extension(kvm, ext); break; } return r; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v3 2/2] arm/arm64: KVM: enable 32 bits kvm vcpu events support
The commit 539aee0edb9f ("KVM: arm64: Share the parts of get/set events useful to 32bit") shares the get/set events helper for arm64 and arm32, it is better also share the check for vcpu events capability to enable 32 bit kvm vcpu events support. User space will check whether KVM supports vcpu events by checking the KVM_CAP_VCPU_EVENTS extension Cc: James Morse Reviewed-by : Suzuki K Poulose Signed-off-by: Dongjiu Geng --- For the 32 bits kvm migration, it needs to enable the vcpu events, this patch will enable it. The user space QEMU patch is here: https://patchwork.ozlabs.org/patch/975615/ --- arch/arm64/kvm/reset.c | 1 - virt/kvm/arm/arm.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index fd37c53..e50245e 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -82,7 +82,6 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: - case KVM_CAP_VCPU_EVENTS: r = 1; break; default: diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 40e79ea..64e5d97 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -212,6 +212,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: case KVM_CAP_MP_STATE: case KVM_CAP_IMMEDIATE_EXIT: + case KVM_CAP_VCPU_EVENTS: r = 1; break; case KVM_CAP_ARM_SET_DEVICE_ADDR: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v3 0/2] rename function name and enable 32bit vcpu events
Rename the kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension, because the name is not reasonable; Enable the 32 bit vcpu events support. Change since v2: 1. Address Suzuki's comments to update the patch commit messages change since v1: 1. Update patch commit messages. Dongjiu Geng (2): arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension() arm/arm64: KVM: enable 32 bits kvm vcpu events support arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 5 ++--- virt/kvm/arm/arm.c| 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v2 2/2] arm/arm64: KVM: enable 32 bits kvm vcpu events support
The commit 539aee0edb9f ("KVM: arm64: Share the parts of get/set events useful to 32bit") shares the get/set events helper for arm64 and arm32, it is better also share the check for vcpu events capability to enable 32 bit kvm vcpu events support. User space will check whether KVM supports vcpu events through KVM_CAP_VCPU_EVENTS IOCTL. Cc: James Morse Signed-off-by: Dongjiu Geng --- For the 32 bits kvm migration, it needs to enable the vcpu events, this patch will enable it. The user space QEMU patch is here: https://patchwork.ozlabs.org/patch/975615/ --- arch/arm64/kvm/reset.c | 1 - virt/kvm/arm/arm.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index fd37c53..e50245e 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -82,7 +82,6 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: - case KVM_CAP_VCPU_EVENTS: r = 1; break; default: diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 40e79ea..64e5d97 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -212,6 +212,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: case KVM_CAP_MP_STATE: case KVM_CAP_IMMEDIATE_EXIT: + case KVM_CAP_VCPU_EVENTS: r = 1; break; case KVM_CAP_ARM_SET_DEVICE_ADDR: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v2 0/2] rename function name and enable 32bit vcpu events
Rename the kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension, because the name is not reasonable; Enable the 32 bit vcpu events support. change since v1: 1. Update patch commit messages. Dongjiu Geng (2): arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension() arm/arm64: KVM: enable 32 bits kvm vcpu events support arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 5 ++--- virt/kvm/arm/arm.c| 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v2 1/2] arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension()
Rename kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension(), because it does not have any relationship with device. Renaming this function can make code readable. Cc: James Morse Signed-off-by: Dongjiu Geng --- I remeber James also mentioned that rename this function. --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 4 ++-- virt/kvm/arm/arm.c| 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 3ad482d..3ee29db 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -273,7 +273,7 @@ static inline void __cpu_init_stage2(void) kvm_call_hyp(__init_stage2_translation); } -static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { return 0; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3d6d733..c20537f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -53,7 +53,7 @@ int __attribute_const__ kvm_target_cpu(void); int kvm_reset_vcpu(struct kvm_vcpu *vcpu); -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext); +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext); void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start); struct kvm_arch { diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78b..fd37c53 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -55,12 +55,12 @@ static bool cpu_has_32bit_el1(void) } /** - * kvm_arch_dev_ioctl_check_extension + * kvm_arch_vm_ioctl_check_extension * * We currently assume that the number of HW registers is uniform * across all CPUs (see cpuinfo_sanity_check). */ -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index c92053b..40e79ea 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -240,7 +240,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = 1; break; default: - r = kvm_arch_dev_ioctl_check_extension(kvm, ext); + r = kvm_arch_vm_ioctl_check_extension(kvm, ext); break; } return r; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH 0/2] rename function name and enable 32bit vcpu events
Rename the kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension, because the name is not reasonable; Enable the 32 bit vcpu events support. Dongjiu Geng (2): arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension() arm/arm64: KVM: share the check for vcpu events capability arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 5 ++--- virt/kvm/arm/arm.c| 3 ++- 4 files changed, 6 insertions(+), 6 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH 1/2] arm/arm64: KVM: rename function kvm_arch_dev_ioctl_check_extension()
Rename kvm_arch_dev_ioctl_check_extension() to kvm_arch_vm_ioctl_check_extension(), because it does not have any relationship with device. Cc: James Morse Signed-off-by: Dongjiu Geng --- I remeber James also mentioned that rename this function. --- arch/arm/include/asm/kvm_host.h | 2 +- arch/arm64/include/asm/kvm_host.h | 2 +- arch/arm64/kvm/reset.c| 4 ++-- virt/kvm/arm/arm.c| 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 3ad482d..3ee29db 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -273,7 +273,7 @@ static inline void __cpu_init_stage2(void) kvm_call_hyp(__init_stage2_translation); } -static inline int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +static inline int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { return 0; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3d6d733..c20537f 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -53,7 +53,7 @@ int __attribute_const__ kvm_target_cpu(void); int kvm_reset_vcpu(struct kvm_vcpu *vcpu); -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext); +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext); void __extended_idmap_trampoline(phys_addr_t boot_pgd, phys_addr_t idmap_start); struct kvm_arch { diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78b..fd37c53 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -55,12 +55,12 @@ static bool cpu_has_32bit_el1(void) } /** - * kvm_arch_dev_ioctl_check_extension + * kvm_arch_vm_ioctl_check_extension * * We currently assume that the number of HW registers is uniform * across all CPUs (see cpuinfo_sanity_check). */ -int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) +int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index c92053b..40e79ea 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -240,7 +240,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) r = 1; break; default: - r = kvm_arch_dev_ioctl_check_extension(kvm, ext); + r = kvm_arch_vm_ioctl_check_extension(kvm, ext); break; } return r; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH 2/2] arm/arm64: KVM: share the check for vcpu events capability
The commit 539aee0edb9f ("KVM: arm64: Share the parts of get/set events useful to 32bit") shares the get/set events helper for arm64 and arm32, it is better also share the check for vcpu events capability. User space will check whether KVM supports vcpu events through KVM_CAP_VCPU_EVENTS IOCTL. Signed-off-by: Dongjiu Geng --- For the 32 bit guest migration, it needs to enable the vcpu events --- arch/arm64/kvm/reset.c | 1 - virt/kvm/arm/arm.c | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index fd37c53..e50245e 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -82,7 +82,6 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext) break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: - case KVM_CAP_VCPU_EVENTS: r = 1; break; default: diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 40e79ea..64e5d97 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -212,6 +212,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_READONLY_MEM: case KVM_CAP_MP_STATE: case KVM_CAP_IMMEDIATE_EXIT: + case KVM_CAP_VCPU_EVENTS: r = 1; break; case KVM_CAP_ARM_SET_DEVICE_ADDR: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] KVM: Documentation: rename the capability of KVM_CAP_ARM_SET_SERROR_ESR
In the documentation description, this capability's name is KVM_CAP_ARM_SET_SERROR_ESR, but in the header file this capability's name is KVM_CAP_ARM_INJECT_SERROR_ESR, so change the documentation description to make it same. Signed-off-by: Dongjiu Geng --- In the Documentation/virtual/kvm/api.txt: +8.19 KVM_CAP_ARM_SET_SERROR_ESR In the include/uapi/linux/kvm.h: +#define KVM_CAP_ARM_INJECT_SERROR_ESR 156 So in above two files, the capability's name is not same, it is better to use a same name. --- Documentation/virtual/kvm/api.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 0acdbac..c664064 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -909,10 +909,10 @@ Serviceability (RAS) Specification"). SError exceptions always have an ESR value. Some CPUs have the ability to specify what the virtual SError's ESR value should be. These systems will -advertise KVM_CAP_ARM_SET_SERROR_ESR. In this case exception.has_esr will +advertise KVM_CAP_ARM_INJECT_SERROR_ESR. In this case exception.has_esr will always have a non-zero value when read, and the agent making an SError pending should specify the ISS field in the lower 24 bits of exception.serror_esr. If -the system supports KVM_CAP_ARM_SET_SERROR_ESR, but user-space sets the events +the system supports KVM_CAP_ARM_INJECT_SERROR_ESR, but user-space sets the events with exception.has_esr as zero, KVM will choose an ESR. Specifying exception.has_esr on a system that does not support it will return @@ -4749,7 +4749,7 @@ hypercalls: HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressList, HvFlushVirtualAddressListEx. -8.19 KVM_CAP_ARM_SET_SERROR_ESR +8.19 KVM_CAP_ARM_INJECT_SERROR_ESR Architectures: arm, arm64 -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] arm64: KVM: rename the capability to set guest SError syndrome
In the documentation description, this capability's name is KVM_CAP_ARM_SET_SERROR_ESR, but in the header file this capability's name is KVM_CAP_ARM_INJECT_SERROR_ESR, so it is better to use a same name. Signed-off-by: Dongjiu Geng --- In the Documentation/virtual/kvm/api.txt: +8.19 KVM_CAP_ARM_SET_SERROR_ESR In the include/uapi/linux/kvm.h: +#define KVM_CAP_ARM_INJECT_SERROR_ESR 156 So in above two files, the capability's name is not same, it is better to use a same name. --- arch/arm64/kvm/reset.c | 2 +- include/uapi/linux/kvm.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index e37c78b..57dc6be 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,7 +77,7 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; - case KVM_CAP_ARM_INJECT_SERROR_ESR: + case KVM_CAP_ARM_SET_SERROR_ESR: r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); break; case KVM_CAP_SET_GUEST_DEBUG: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 07548de..fab7525 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -951,7 +951,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_HYPERV_TLBFLUSH 155 #define KVM_CAP_S390_HPAGE_1M 156 #define KVM_CAP_NESTED_STATE 157 -#define KVM_CAP_ARM_INJECT_SERROR_ESR 158 +#define KVM_CAP_ARM_SET_SERROR_ESR 158 #ifdef KVM_CAP_IRQ_ROUTING -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH RESEND v6 0/2] support exception state migration and set VSESR_EL2 by user space
This series patch is separated from https://www.spinics.net/lists/kvm/msg168917.html 1. Detect whether KVM can set set guest SError syndrome 2. Support to Set VSESR_EL2 and inject SError by user space. 3. Support live migration to keep SError pending state and VSESR_EL2 value The user space patch is here: https://www.mail-archive.com/qemu-devel@nongnu.org/msg539534.html BTW: The user space patch is needed to rebase Dongjiu Geng (2): arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS arm64: KVM: export the capability to set guest SError syndrome Documentation/virtual/kvm/api.txt| 44 ++ arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 ++ arch/arm64/include/uapi/asm/kvm.h| 13 ++ arch/arm64/kvm/guest.c | 46 arch/arm64/kvm/inject_fault.c| 6 ++--- arch/arm64/kvm/reset.c | 4 include/uapi/linux/kvm.h | 1 + virt/kvm/arm/arm.c | 21 9 files changed, 140 insertions(+), 7 deletions(-) -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH RESEND v6 2/2] arm64: KVM: export the capability to set guest SError syndrome
For the arm64 RAS Extension, user space can inject a virtual-SError with specified ESR. So user space needs to know whether KVM support to inject such SError, this interface adds this query for this capability. KVM will check whether system support RAS Extension, if supported, KVM returns true to user space, otherwise returns false. Signed-off-by: Dongjiu Geng Reviewed-by: James Morse --- change since v5: 1. Rebase this patch to v4.18-rc3 --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e3940f8..480fa64 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4643,3 +4643,14 @@ This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush hypercalls: HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressList, HvFlushVirtualAddressListEx. + +8.19 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify the syndrome value reported +to the guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, it can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +in ISS filed of ESR_EL1. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index a3db01a..067c6ba 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: case KVM_CAP_VCPU_EVENTS: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index b6270a3..a7d9bc4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -949,6 +949,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_GET_MSR_FEATURES 153 #define KVM_CAP_HYPERV_EVENTFD 154 #define KVM_CAP_HYPERV_TLBFLUSH 155 +#define KVM_CAP_ARM_INJECT_SERROR_ESR 156 #ifdef KVM_CAP_IRQ_ROUTING -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH RESEND v6 1/2] arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS
For the migrating VMs, user space may need to know the exception state. For example, in the machine A, KVM make an SError pending, when migrate to B, KVM also needs to pend an SError. This new IOCTL exports user-invisible states related to SError. Together with appropriate user space changes, user space can get/set the SError exception state to do migrate/snapshot/suspend. Signed-off-by: Dongjiu Geng Reviewed-by: James Morse --- change since v5: Address James's comments, thanks James's review 1. Check check against the top bits of ESR change since v4: Address Christoffer's comments, thanks Christoffer's review. 1. Change the 'Capebility' to 'Capability' to fix the typo issue 2. Not wrap the line below 80 chars on a single line in kvm_arm_vcpu_get_events() 3. Re-ordere the patch 1 and patch 2 Address Marc's comments, thanks Marc's review 1. Remove the "else" clause in kvm_arm_vcpu_get_events() 2. Check all the padding in the kvm_vcpu_events is set to zero Address James's comments, thanks James's review 1. Change to "vcpu ioctl" to fix the documentation 2. Using __KVM_HAVE_VCPU_EVENTS to control ARM64 compilation 3. Check the padding[] and reserved[] are zero Change since v3: 1. Fix the memset() issue in the kvm_arm_vcpu_get_events() change since v2: 1. Add kvm_vcpu_events structure definition for arm platform to avoid the build errors. change since v1: Address Marc's comments, thanks Marc's review 1. serror_has_esr always true when ARM64_HAS_RAS_EXTN is set 2. remove Spurious blank line in kvm_arm_vcpu_set_events() 3. rename pend_guest_serror() to kvm_set_sei_esr() 4. Make kvm_arm_vcpu_get_events() did all the work rather than having this split responsibility. 5. using sizeof(events) instead of sizeof(struct kvm_vcpu_events) this series patch is separated from https://www.spinics.net/lists/kvm/msg168917.html The user space patch is here: https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg06965.html change since V12: 1. change (vcpu->arch.hcr_el2 & HCR_VSE) to !!(vcpu->arch.hcr_el2 & HCR_VSE) in kvm_arm_vcpu_get_events() Change since V11: Address James's comments, thanks James 1. Align the struct of kvm_vcpu_events to 64 bytes 2. Avoid exposing the stale ESR value in the kvm_arm_vcpu_get_events() 3. Change variables 'injected' name to 'serror_pending' in the kvm_arm_vcpu_set_events() 4. Change to sizeof(events) from sizeof(struct kvm_vcpu_events) in kvm_arch_vcpu_ioctl() Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. --- Documentation/virtual/kvm/api.txt| 33 ++ arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 ++ arch/arm64/include/uapi/asm/kvm.h| 13 ++ arch/arm64/kvm/guest.c | 46 arch/arm64/kvm/inject_fault.c| 6 ++--- arch/arm64/kvm/reset.c | 1 + virt/kvm/arm/arm.c | 21 8 files changed, 125 insertions(+), 7 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index d10944e..e3940f8 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -835,11 +835,13 @@ struct kvm_clock_data { Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 -Type: vm ioctl +Architectures: x86, arm64 +Type: vcpu ioctl Parameters: struct kvm_vcpu_event (out) Returns: 0 on success, -1 on error +X86: + Gets currently pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -881,15 +883,32 @@ Only two fields are defined in the flags field: - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that smi contains a valid state. +ARM64: + +Gets currently pending SError exceptions as well as related states of the vcpu. + +struct kvm_vcpu_events { + struct { + __u8 serror_pending; + __u8 serror_has_esr; + /* Align it to 8 bytes */ + __u8 pad[6]; + __u64 serror_esr; + } exception; + __u32 reserved[12]; +}; + 4.32 KVM_SET_VCPU_EVENTS Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 -Type: vm ioctl +Architectures: x86, arm64 +Type: vcpu ioctl Parameters: struct kvm_vcpu_event (in) Returns: 0 on success, -1 on error +X86: + Set pending exceptions, interrupts, and NMIs as well as related states of the v
[PATCH v6 1/2] arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS
For the migrating VMs, user space may need to know the exception state. For example, in the machine A, KVM make an SError pending, when migrate to B, KVM also needs to pend an SError. This new IOCTL exports user-invisible states related to SError. Together with appropriate user space changes, user space can get/set the SError exception state to do migrate/snapshot/suspend. Signed-off-by: Dongjiu Geng Reviewed-by: James Morse --- change since v5: Address James's comments, thanks James's review 1. Check check against the top bits of ESR change since v4: Address Christoffer's comments, thanks Christoffer's review. 1. Change the 'Capebility' to 'Capability' to fix the typo issue 2. Not wrap the line below 80 chars on a single line in kvm_arm_vcpu_get_events() 3. Re-ordere the patch 1 and patch 2 Address Marc's comments, thanks Marc's review 1. Remove the "else" clause in kvm_arm_vcpu_get_events() 2. Check all the padding in the kvm_vcpu_events is set to zero Address James's comments, thanks James's review 1. Change to "vcpu ioctl" to fix the documentation 2. Using __KVM_HAVE_VCPU_EVENTS to control ARM64 compilation 3. Check the padding[] and reserved[] are zero Change since v3: 1. Fix the memset() issue in the kvm_arm_vcpu_get_events() change since v2: 1. Add kvm_vcpu_events structure definition for arm platform to avoid the build errors. change since v1: Address Marc's comments, thanks Marc's review 1. serror_has_esr always true when ARM64_HAS_RAS_EXTN is set 2. remove Spurious blank line in kvm_arm_vcpu_set_events() 3. rename pend_guest_serror() to kvm_set_sei_esr() 4. Make kvm_arm_vcpu_get_events() did all the work rather than having this split responsibility. 5. using sizeof(events) instead of sizeof(struct kvm_vcpu_events) this series patch is separated from https://www.spinics.net/lists/kvm/msg168917.html The user space patch is here: https://lists.gnu.org/archive/html/qemu-devel/2018-05/msg06965.html change since V12: 1. change (vcpu->arch.hcr_el2 & HCR_VSE) to !!(vcpu->arch.hcr_el2 & HCR_VSE) in kvm_arm_vcpu_get_events() Change since V11: Address James's comments, thanks James 1. Align the struct of kvm_vcpu_events to 64 bytes 2. Avoid exposing the stale ESR value in the kvm_arm_vcpu_get_events() 3. Change variables 'injected' name to 'serror_pending' in the kvm_arm_vcpu_set_events() 4. Change to sizeof(events) from sizeof(struct kvm_vcpu_events) in kvm_arch_vcpu_ioctl() Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. --- Documentation/virtual/kvm/api.txt| 33 ++ arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 ++ arch/arm64/include/uapi/asm/kvm.h| 13 ++ arch/arm64/kvm/guest.c | 46 arch/arm64/kvm/inject_fault.c| 6 ++--- arch/arm64/kvm/reset.c | 1 + virt/kvm/arm/arm.c | 21 8 files changed, 125 insertions(+), 7 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index d10944e..e3940f8 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -835,11 +835,13 @@ struct kvm_clock_data { Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 -Type: vm ioctl +Architectures: x86, arm64 +Type: vcpu ioctl Parameters: struct kvm_vcpu_event (out) Returns: 0 on success, -1 on error +X86: + Gets currently pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -881,15 +883,32 @@ Only two fields are defined in the flags field: - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that smi contains a valid state. +ARM64: + +Gets currently pending SError exceptions as well as related states of the vcpu. + +struct kvm_vcpu_events { + struct { + __u8 serror_pending; + __u8 serror_has_esr; + /* Align it to 8 bytes */ + __u8 pad[6]; + __u64 serror_esr; + } exception; + __u32 reserved[12]; +}; + 4.32 KVM_SET_VCPU_EVENTS Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 -Type: vm ioctl +Architectures: x86, arm64 +Type: vcpu ioctl Parameters: struct kvm_vcpu_event (in) Returns: 0 on success, -1 on error +X86: + Set pending exceptions, interrupts, and NMIs as well as related states of the v
[PATCH v6 0/2] support exception state migration and set VSESR_EL2 by user space
This series patch is separated from https://www.spinics.net/lists/kvm/msg168917.html 1. Detect whether KVM can set set guest SError syndrome 2. Support to Set VSESR_EL2 and inject SError by user space. 3. Support live migration to keep SError pending state and VSESR_EL2 value The user space patch is here: https://www.mail-archive.com/qemu-devel@nongnu.org/msg539534.html BTW: The user space patch is needed to rebase Dongjiu Geng (2): arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS arm64: KVM: export the capability to set guest SError syndrome Documentation/virtual/kvm/api.txt| 44 ++ arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 ++ arch/arm64/include/uapi/asm/kvm.h| 13 ++ arch/arm64/kvm/guest.c | 46 arch/arm64/kvm/inject_fault.c| 6 ++--- arch/arm64/kvm/reset.c | 4 include/uapi/linux/kvm.h | 1 + virt/kvm/arm/arm.c | 21 9 files changed, 140 insertions(+), 7 deletions(-) -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 2/2] arm64: KVM: export the capability to set guest SError syndrome
For the arm64 RAS Extension, user space can inject a virtual-SError with specified ESR. So user space needs to know whether KVM support to inject such SError, this interface adds this query for this capability. KVM will check whether system support RAS Extension, if supported, KVM returns true to user space, otherwise returns false. Signed-off-by: Dongjiu Geng Reviewed-by: James Morse --- change since v5: 1. Rebase this patch to v4.18-rc3 --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e3940f8..480fa64 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4643,3 +4643,14 @@ This capability indicates that KVM supports paravirtualized Hyper-V TLB Flush hypercalls: HvFlushVirtualAddressSpace, HvFlushVirtualAddressSpaceEx, HvFlushVirtualAddressList, HvFlushVirtualAddressListEx. + +8.19 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify the syndrome value reported +to the guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, it can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +in ISS filed of ESR_EL1. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index a3db01a..067c6ba 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: case KVM_CAP_VCPU_EVENTS: diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index b6270a3..a7d9bc4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -949,6 +949,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_GET_MSR_FEATURES 153 #define KVM_CAP_HYPERV_EVENTFD 154 #define KVM_CAP_HYPERV_TLBFLUSH 155 +#define KVM_CAP_ARM_INJECT_SERROR_ESR 156 #ifdef KVM_CAP_IRQ_ROUTING -- 2.7.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v12 3/4] ACPI / APEI: Add SEI notification type support for ARMv8
ACPI 6.x adds support for NOTIFY_SEI as a GHES notification mechanism, so add new GHES notification handling functions. Expose API ghes_notify_sei() to arch code, arch code will call this API when it gets this NOTIFY_SEI. Signed-off-by: Dongjiu Geng Note: Firmware will follow the SError mask rule, if the SError is masked, the firmware will not deliver NOTIFY_SEI notification. --- drivers/acpi/apei/Kconfig | 15 ++ drivers/acpi/apei/ghes.c | 53 +++ include/acpi/ghes.h | 1 + 3 files changed, 69 insertions(+) diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 52ae543..ff4afc3 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -55,6 +55,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI SError(System Error) Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (SError interrupt). + + SEI happens with asynchronous external abort for errors on device + memory reads on ARMv8 systems. If a system supports firmware first + handling of SEI, the platform analyzes and handles hardware error + notifications from SEI, and it may then form a hardware error record for + the OS to parse and handle. This option allows the OS to look for + such hardware error record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 1efefe9..33f77ae 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -827,6 +827,46 @@ static inline void ghes_sea_add(struct ghes *ghes) { } static inline void ghes_sea_remove(struct ghes *ghes) { } #endif /* CONFIG_ACPI_APEI_SEA */ +#ifdef CONFIG_ACPI_APEI_SEI +static LIST_HEAD(ghes_sei); + +/* + * Return 0 only if one of the SEI error sources successfully reported an error + * record sent from the firmware. + */ +int ghes_notify_sei(void) +{ + struct ghes *ghes; + int ret = -ENOENT; + + rcu_read_lock(); + list_for_each_entry_rcu(ghes, &ghes_sei, list) { + if (!ghes_proc(ghes)) + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +static void ghes_sei_add(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); +} + +static void ghes_sei_remove(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_del_rcu(&ghes->list); + mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); +} +#else /* CONFIG_ACPI_APEI_SEI */ +static inline void ghes_sei_add(struct ghes *ghes) { } +static inline void ghes_sei_remove(struct ghes *ghes) { } +#endif /* CONFIG_ACPI_APEI_SEI */ + #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* * printk is not safe in NMI context. So in NMI handler, we allocate @@ -1055,6 +1095,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1126,6 +1173,9 @@ static int ghes_probe(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_add(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_add(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); break; @@ -1179,6 +1229,9 @@ static int ghes_remove(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_remove(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_remove(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); break; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c8..9ba59e2 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -120,5 +120,6 @@ static inline void *acpi_hest_get_next(
[PATCH v12 4/4] arm64: handle NOTIFY_SEI notification by the APEI driver
Add a helper to handle the NOTIFY_SEI notification, when kernel gets the NOTIFY_SEI notification, call this helper and let APEI driver to handle this notification. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/traps.c| 4 arch/arm64/mm/fault.c| 10 ++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..9ee13ad 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index bbb0fde..d888eb2 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -681,6 +681,10 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) { u32 aet = arm64_ras_serror_get_severity(esr); + /* The APEI driver may handle this RAS error. */ + if (!handle_guest_sei()) + return false; + switch (aet) { case ESR_ELx_AET_CE:/* corrected error */ case ESR_ELx_AET_UEO: /* restartable, not yet consumed */ diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index f76bb2c..8f29bd8 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -683,6 +683,16 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) return ret; } +int handle_guest_sei(void) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_sei(); + + return ret; +} + asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v12 0/4] set VSESR_EL2 by user space and support NOTIFY_SEI notification
1. Detect whether KVM can set set guest SError syndrome 2. Support to Set VSESR_EL2 and inject SError by user space. 3. Support live migration to keep SError pending state and VSESR_EL2 value. 4. ACPI 6.1 adds support for NOTIFY_SEI as a GHES notification mechanism, so support this notification in software, KVM or kernel ARCH code call handle_guest_sei() to let ACP driver to handle this notification. Change since V11: Address James's comments, thanks James 1. Align the struct of kvm_vcpu_events to 64 bytes 2. Avoid exposing the stale ESR value in the kvm_arm_vcpu_get_events() 3. Change variables 'injected' name to 'serror_pending' in the kvm_arm_vcpu_set_events() 4. Change to sizeof(events) from sizeof(struct kvm_vcpu_events) in kvm_arch_vcpu_ioctl() 5. Update the patches commit message and document description Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. Dongjiu Geng (4): arm64: KVM: export the capability to set guest SError syndrome arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS ACPI / APEI: Add SEI notification type support for ARMv8 arm64: handle NOTIFY_SEI notification by the APEI driver Documentation/virtual/kvm/api.txt| 42 ++-- arch/arm/include/asm/kvm_host.h | 6 arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 + arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/include/uapi/asm/kvm.h| 13 + arch/arm64/kernel/traps.c| 4 +++ arch/arm64/kvm/guest.c | 36 arch/arm64/kvm/inject_fault.c| 7 - arch/arm64/kvm/reset.c | 4 +++ arch/arm64/mm/fault.c| 10 +++ drivers/acpi/apei/Kconfig| 15 ++ drivers/acpi/apei/ghes.c | 53 include/acpi/ghes.h | 1 + include/uapi/linux/kvm.h | 1 + virt/kvm/arm/arm.c | 21 ++ 17 files changed, 234 insertions(+), 4 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v12 2/4] arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS
For the migrating VMs, user space may need to know the exception state. For example, in the machine A, KVM make an SError pending, when migrate to B, KVM also needs to pend an SError. This new IOCTL exports user-invisible states related to SError. Together with appropriate user space changes, user space can get/set the SError exception state to do migrate/snapshot/suspend. Signed-off-by: Dongjiu Geng Change since V11: Address James's comments, thanks James 1. Align the struct of kvm_vcpu_events to 64 bytes 2. Avoid exposing the stale ESR value in the kvm_arm_vcpu_get_events() 3. Change variables 'injected' name to 'serror_pending' in the kvm_arm_vcpu_set_events() 4. change to sizeof(events) from sizeof(struct kvm_vcpu_events) in kvm_arch_vcpu_ioctl() Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. --- Documentation/virtual/kvm/api.txt| 31 --- arch/arm/include/asm/kvm_host.h | 6 ++ arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_emulate.h | 5 + arch/arm64/include/asm/kvm_host.h| 7 +++ arch/arm64/include/uapi/asm/kvm.h| 13 + arch/arm64/kvm/guest.c | 36 arch/arm64/kvm/inject_fault.c| 7 ++- arch/arm64/kvm/reset.c | 1 + virt/kvm/arm/arm.c | 21 + 10 files changed, 135 insertions(+), 4 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 66494a5..36a9dc3 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -819,11 +819,13 @@ struct kvm_clock_data { Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (out) Returns: 0 on success, -1 on error +X86: + Gets currently pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -865,15 +867,32 @@ Only two fields are defined in the flags field: - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that smi contains a valid state. +ARM, ARM64: + +Gets currently pending SError exceptions as well as related states of the vcpu. + +struct kvm_vcpu_events { + struct { + __u8 serror_pending; + __u8 serror_has_esr; + /* Align it to 8 bytes */ + __u8 pad[6]; + __u64 serror_esr; + } exception; + __u32 reserved[12]; +}; + 4.32 KVM_SET_VCPU_EVENTS -Capability: KVM_CAP_VCPU_EVENTS +Capebility: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (in) Returns: 0 on success, -1 on error +X86: + Set pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -894,6 +913,12 @@ shall be written into the VCPU. KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available. +ARM, ARM64: + +Set pending SError exceptions as well as related states of the vcpu. + +See KVM_GET_VCPU_EVENTS for the data structure. + 4.33 KVM_GET_DEBUGREGS diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index ef54013..d81621e 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,12 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..39f895d 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,18 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(
[PATCH v12 1/4] arm64: KVM: export the capability to set guest SError syndrome
For the arm64 RAS Extension, user space can inject a virtual-SError with specified ESR. So user space needs to know whether KVM support to inject such SError, this interface adds this query for this capability. KVM will check whether system support RAS Extension, if supported, KVM returns true to user space, otherwise returns false. Signed-off-by: Dongjiu Geng Reviewed-by: James Morse Change from V11: 1. Change the commit message 2. Update the Documentation/virtual/kvm/api.tx --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index fc3ae95..66494a5 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4415,3 +4415,14 @@ Parameters: none This capability indicates if the flic device will be able to get/set the AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows to discover this without having to create a flic device. + +8.14 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify the syndrome value reported +to the guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, it can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +in ISS filed of ESR_EL1. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..38c8a64 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 8fb90a0..3587b33 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -934,6 +934,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_AIS_MIGRATION 150 #define KVM_CAP_PPC_GET_CPU_CHAR 151 #define KVM_CAP_S390_BPB 152 +#define KVM_CAP_ARM_INJECT_SERROR_ESR 153 #ifdef KVM_CAP_IRQ_ROUTING -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v11 1/4] arm64: KVM: export the capability to set guest SError syndrome
Before user space injects a SError, it needs to know whether it can specify the guest Exception Syndrome, so KVM should tell user space whether it has such capability. Signed-off-by: Dongjiu Geng --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index fc3ae95..8a3d708 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4415,3 +4415,14 @@ Parameters: none This capability indicates if the flic device will be able to get/set the AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows to discover this without having to create a flic device. + +8.14 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify syndrome value reported to +guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +into ISS filed of ESR_EL1. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..38c8a64 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 8fb90a0..3587b33 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -934,6 +934,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_AIS_MIGRATION 150 #define KVM_CAP_PPC_GET_CPU_CHAR 151 #define KVM_CAP_S390_BPB 152 +#define KVM_CAP_ARM_INJECT_SERROR_ESR 153 #ifdef KVM_CAP_IRQ_ROUTING -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v11 2/4] arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS
This new IOCTL exports user-invisible states related to SError. Together with appropriate user space changes, it can inject SError with specified syndrome to guest by setup kvm_vcpu_events value. Also it can support live migration. Signed-off-by: Dongjiu Geng Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. --- Documentation/virtual/kvm/api.txt| 28 ++-- arch/arm/include/asm/kvm_host.h | 6 ++ arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_emulate.h | 5 + arch/arm64/include/asm/kvm_host.h| 7 +++ arch/arm64/include/uapi/asm/kvm.h| 12 arch/arm64/kvm/guest.c | 31 +++ arch/arm64/kvm/inject_fault.c| 7 ++- arch/arm64/kvm/reset.c | 1 + virt/kvm/arm/arm.c | 21 + 10 files changed, 127 insertions(+), 3 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 8a3d708..45719b4 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -819,11 +819,13 @@ struct kvm_clock_data { Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (out) Returns: 0 on success, -1 on error +X86: + Gets currently pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -865,15 +867,31 @@ Only two fields are defined in the flags field: - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that smi contains a valid state. +ARM, ARM64: + +Gets currently pending SError exceptions as well as related states of the vcpu. + +struct kvm_vcpu_events { + struct { + __u8 serror_pending; + __u8 serror_has_esr; + /* Align it to 4 bytes */ + __u8 pad[2]; + __u64 serror_esr; + } exception; +}; + 4.32 KVM_SET_VCPU_EVENTS Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (in) Returns: 0 on success, -1 on error +X86: + Set pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -894,6 +912,12 @@ shall be written into the VCPU. KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available. +ARM, ARM64: + +Set pending SError exceptions as well as related states of the vcpu. + +See KVM_GET_VCPU_EVENTS for the data structure. + 4.33 KVM_GET_DEBUGREGS diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index ef54013..d81621e 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,12 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..39f895d 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,18 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 413dc82..3294885 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -71,6 +71,11 @@ static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) vcpu->arch.hcr_el2 = hcr; } +static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.vsesr_el2; +} + static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr) { vcpu->arch
[PATCH v11 3/4] ACPI / APEI: Add SEI notification type support for ARMv8
ACPI 6.x adds support for NOTIFY_SEI as a GHES notification mechanism, so add new GHES notification handling functions. Expose API ghes_notify_sei() to arch code, arch code will call this API when it gets this NOTIFY_SEI. Signed-off-by: Dongjiu Geng --- drivers/acpi/apei/Kconfig | 15 ++ drivers/acpi/apei/ghes.c | 53 +++ include/acpi/ghes.h | 1 + 3 files changed, 69 insertions(+) diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 52ae543..ff4afc3 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -55,6 +55,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI SError(System Error) Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (SError interrupt). + + SEI happens with asynchronous external abort for errors on device + memory reads on ARMv8 systems. If a system supports firmware first + handling of SEI, the platform analyzes and handles hardware error + notifications from SEI, and it may then form a hardware error record for + the OS to parse and handle. This option allows the OS to look for + such hardware error record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 1efefe9..33f77ae 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -827,6 +827,46 @@ static inline void ghes_sea_add(struct ghes *ghes) { } static inline void ghes_sea_remove(struct ghes *ghes) { } #endif /* CONFIG_ACPI_APEI_SEA */ +#ifdef CONFIG_ACPI_APEI_SEI +static LIST_HEAD(ghes_sei); + +/* + * Return 0 only if one of the SEI error sources successfully reported an error + * record sent from the firmware. + */ +int ghes_notify_sei(void) +{ + struct ghes *ghes; + int ret = -ENOENT; + + rcu_read_lock(); + list_for_each_entry_rcu(ghes, &ghes_sei, list) { + if (!ghes_proc(ghes)) + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +static void ghes_sei_add(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); +} + +static void ghes_sei_remove(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_del_rcu(&ghes->list); + mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); +} +#else /* CONFIG_ACPI_APEI_SEI */ +static inline void ghes_sei_add(struct ghes *ghes) { } +static inline void ghes_sei_remove(struct ghes *ghes) { } +#endif /* CONFIG_ACPI_APEI_SEI */ + #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* * printk is not safe in NMI context. So in NMI handler, we allocate @@ -1055,6 +1095,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1126,6 +1173,9 @@ static int ghes_probe(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_add(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_add(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); break; @@ -1179,6 +1229,9 @@ static int ghes_remove(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_remove(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_remove(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); break; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c8..9ba59e2 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -120,5 +120,6 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata) section = acpi_hest_get_next(section)) int ghes_notify_sea(void); +int ghes_notify_se
[PATCH v11 4/4] arm64: handle NOTIFY_SEI notification by the APEI driver
Add a helper to handle the NOTIFY_SEI notification, when kernel gets the NOTIFY_SEI notification, call this helper and let APEI driver to handle this notification. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/traps.c| 4 arch/arm64/mm/fault.c| 10 ++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..9ee13ad 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index bbb0fde..d888eb2 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -681,6 +681,10 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) { u32 aet = arm64_ras_serror_get_severity(esr); + /* The APEI driver may handle this RAS error. */ + if (!handle_guest_sei()) + return false; + switch (aet) { case ESR_ELx_AET_CE:/* corrected error */ case ESR_ELx_AET_UEO: /* restartable, not yet consumed */ diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index f76bb2c..8f29bd8 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -683,6 +683,16 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) return ret; } +int handle_guest_sei(void) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_sei(); + + return ret; +} + asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v11 0/4] set VSESR_EL2 by user space and support NOTIFY_SEI notification
1. Detect whether KVM can set set guest SError syndrome 2. Support to Set VSESR_EL2 and inject SError by user space. 3. Support live migration to keep SError pending state and VSESR_EL2 value. 4. ACPI 6.1 adds support for NOTIFY_SEI as a GHES notification mechanism, so support this notification in software, KVM or kernel ARCH code call handle_guest_sei() to let ACP driver to handle this notification. Change since V10: Address James's comments, thanks James 1. Merge the helper function with the user. 2. Move the ISS_MASK into pend_guest_serror() to clear top bits 3. Make kvm_vcpu_events struct align to 4 bytes 4. Add something check in the kvm_arm_vcpu_set_events() 5. Check kvm_arm_vcpu_get/set_events()'s return value. 6. Initialise kvm_vcpu_events to 0 so that padding transferred to user-space doesn't contain kernel stack. Dongjiu Geng (4): arm64: KVM: export the capability to set guest SError syndrome arm/arm64: KVM: Add KVM_GET/SET_VCPU_EVENTS ACPI / APEI: Add SEI notification type support for ARMv8 arm64: handle NOTIFY_SEI notification by the APEI driver Documentation/virtual/kvm/api.txt| 39 -- arch/arm/include/asm/kvm_host.h | 6 arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 + arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/include/uapi/asm/kvm.h| 12 arch/arm64/kernel/traps.c| 4 +++ arch/arm64/kvm/guest.c | 31 + arch/arm64/kvm/inject_fault.c| 7 - arch/arm64/kvm/reset.c | 4 +++ arch/arm64/mm/fault.c| 10 +++ drivers/acpi/apei/Kconfig| 15 ++ drivers/acpi/apei/ghes.c | 53 include/acpi/ghes.h | 1 + include/uapi/linux/kvm.h | 1 + virt/kvm/arm/arm.c | 21 ++ 17 files changed, 226 insertions(+), 3 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v10 3/5] arm/arm64: KVM: Introduce set and get per-vcpu event
RAS Extension provides VSESR_EL2 register to specify virtual SError syndrome value, this patch adds a new IOCTL to export user-invisible states related to SError exceptions. User space can setup the kvm_vcpu_events to inject specified SError, also it can support live migration. Signed-off-by: Dongjiu Geng --- Documentation/virtual/kvm/api.txt | 26 -- arch/arm/include/asm/kvm_host.h | 6 ++ arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_host.h | 5 + arch/arm64/include/uapi/asm/kvm.h | 10 ++ arch/arm64/kvm/guest.c| 26 ++ arch/arm64/kvm/reset.c| 1 + virt/kvm/arm/arm.c| 18 ++ 8 files changed, 102 insertions(+), 2 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 8a3d708..26ae151 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -819,11 +819,13 @@ struct kvm_clock_data { Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (out) Returns: 0 on success, -1 on error +X86: + Gets currently pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -865,15 +867,29 @@ Only two fields are defined in the flags field: - KVM_VCPUEVENT_VALID_SMM may be set in the flags field to signal that smi contains a valid state. +ARM, ARM64: + +Gets currently pending SError exceptions as well as related states of the vcpu. + +struct kvm_vcpu_events { + struct { + bool serror_pending; + bool serror_has_esr; + u64 serror_esr; + } exception; +}; + 4.32 KVM_SET_VCPU_EVENTS Capability: KVM_CAP_VCPU_EVENTS Extended by: KVM_CAP_INTR_SHADOW -Architectures: x86 +Architectures: x86, arm, arm64 Type: vm ioctl Parameters: struct kvm_vcpu_event (in) Returns: 0 on success, -1 on error +X86: + Set pending exceptions, interrupts, and NMIs as well as related states of the vcpu. @@ -894,6 +910,12 @@ shall be written into the VCPU. KVM_VCPUEVENT_VALID_SMM can only be set if KVM_CAP_X86_SMM is available. +ARM, ARM64: + +Set pending SError exceptions as well as related states of the vcpu. + +See KVM_GET_VCPU_EVENTS for the data structure. + 4.33 KVM_GET_DEBUGREGS diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index ef54013..d81621e 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,12 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..39f895d 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,18 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 3dc49b7..1125540 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -326,6 +326,11 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_vcpu_get_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); + +int kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, + struct kvm_vcpu_events *events); #define KVM_ARCH_WANT_MMU_NOTIFIER int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 9abbf30..32c0eae 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -39,6 +39,7 @@ #define __KVM_HAVE_GUEST_DEBUG #define __KVM_HAVE_IRQ_LINE #define __KVM_HAVE_READONLY_MEM +#define __KVM_HAVE_VCPU_EVENTS #define KVM_COALESCED_MMIO_PAGE_OFFSET 1
[PATCH v10 2/5] arm64: KVM: export the capability to set guest SError syndrome
Before user space injects a SError, it needs to know whether it can specify the guest Exception Syndrome, so KVM should tell user space whether it has such capability. Signed-off-by: Dongjiu Geng --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 1 + 3 files changed, 15 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index fc3ae95..8a3d708 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4415,3 +4415,14 @@ Parameters: none This capability indicates if the flic device will be able to get/set the AIS states for migration via the KVM_DEV_FLIC_AISM_ALL attribute and allows to discover this without having to create a flic device. + +8.14 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify syndrome value reported to +guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +into ISS filed of ESR_EL1. diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..38c8a64 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 8fb90a0..3587b33 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -934,6 +934,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_S390_AIS_MIGRATION 150 #define KVM_CAP_PPC_GET_CPU_CHAR 151 #define KVM_CAP_S390_BPB 152 +#define KVM_CAP_ARM_INJECT_SERROR_ESR 153 #ifdef KVM_CAP_IRQ_ROUTING -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v10 1/5] arm64: KVM: Prepare set virtual SEI syndrome value
Export one API to specify virtual SEI syndrome value for guest, and add a helper to get the VSESR_EL2 value. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_emulate.h | 5 + arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/kvm/inject_fault.c| 5 + 3 files changed, 12 insertions(+) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 413dc82..3294885 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -71,6 +71,11 @@ static inline void vcpu_set_hcr(struct kvm_vcpu *vcpu, unsigned long hcr) vcpu->arch.hcr_el2 = hcr; } +static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu) +{ + return vcpu->arch.vsesr_el2; +} + static inline void vcpu_set_vsesr(struct kvm_vcpu *vcpu, u64 vsesr) { vcpu->arch.vsesr_el2 = vsesr; diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index a73f63a..3dc49b7 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -354,6 +354,8 @@ void handle_exit_early(struct kvm_vcpu *vcpu, struct kvm_run *run, int kvm_perf_init(void); int kvm_perf_teardown(void); +void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome); + struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr); static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index 60666a0..78ecb28 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -186,3 +186,8 @@ void kvm_inject_vabt(struct kvm_vcpu *vcpu) { pend_guest_serror(vcpu, ESR_ELx_ISV); } + +void kvm_set_sei_esr(struct kvm_vcpu *vcpu, u64 syndrome) +{ + pend_guest_serror(vcpu, syndrome & ESR_ELx_ISS_MASK); +} -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v10 5/5] arm64: handle NOTIFY_SEI notification by the APEI driver
Add a helper to handle the NOTIFY_SEI notification, when kernel gets the NOTIFY_SEI notification, call this helper and let APEI driver to handle this notification. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/traps.c| 4 arch/arm64/mm/fault.c| 10 ++ 3 files changed, 15 insertions(+) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..9ee13ad 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index e88096a..6cb280f 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -681,6 +681,10 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) { u32 aet = arm64_ras_serror_get_severity(esr); + /* The APEI driver may handle this RAS error. */ + if (!handle_guest_sei()) + return false; + switch (aet) { case ESR_ELx_AET_CE:/* corrected error */ case ESR_ELx_AET_UEO: /* restartable, not yet consumed */ diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index f76bb2c..8f29bd8 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -683,6 +683,16 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) return ret; } +int handle_guest_sei(void) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_sei(); + + return ret; +} + asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, struct pt_regs *regs) { -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v10 4/5] ACPI / APEI: Add SEI notification type support for ARMv8
ACPI 6.x adds support for NOTIFY_SEI as a GHES notification mechanism, so add new GHES notification handling functions. Expose API ghes_notify_sei() to arch code, arch code will call this API when it gets this NOTIFY_SEI. Signed-off-by: Dongjiu Geng --- drivers/acpi/apei/Kconfig | 15 ++ drivers/acpi/apei/ghes.c | 53 +++ include/acpi/ghes.h | 1 + 3 files changed, 69 insertions(+) diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 52ae543..ff4afc3 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -55,6 +55,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI SError(System Error) Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (SError interrupt). + + SEI happens with asynchronous external abort for errors on device + memory reads on ARMv8 systems. If a system supports firmware first + handling of SEI, the platform analyzes and handles hardware error + notifications from SEI, and it may then form a hardware error record for + the OS to parse and handle. This option allows the OS to look for + such hardware error record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 1efefe9..33f77ae 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -827,6 +827,46 @@ static inline void ghes_sea_add(struct ghes *ghes) { } static inline void ghes_sea_remove(struct ghes *ghes) { } #endif /* CONFIG_ACPI_APEI_SEA */ +#ifdef CONFIG_ACPI_APEI_SEI +static LIST_HEAD(ghes_sei); + +/* + * Return 0 only if one of the SEI error sources successfully reported an error + * record sent from the firmware. + */ +int ghes_notify_sei(void) +{ + struct ghes *ghes; + int ret = -ENOENT; + + rcu_read_lock(); + list_for_each_entry_rcu(ghes, &ghes_sei, list) { + if (!ghes_proc(ghes)) + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +static void ghes_sei_add(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); +} + +static void ghes_sei_remove(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_del_rcu(&ghes->list); + mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); +} +#else /* CONFIG_ACPI_APEI_SEI */ +static inline void ghes_sei_add(struct ghes *ghes) { } +static inline void ghes_sei_remove(struct ghes *ghes) { } +#endif /* CONFIG_ACPI_APEI_SEI */ + #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* * printk is not safe in NMI context. So in NMI handler, we allocate @@ -1055,6 +1095,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1126,6 +1173,9 @@ static int ghes_probe(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_add(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_add(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); break; @@ -1179,6 +1229,9 @@ static int ghes_remove(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_remove(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_remove(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); break; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c8..9ba59e2 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -120,5 +120,6 @@ static inline void *acpi_hest_get_next(struct acpi_hest_generic_data *gdata) section = acpi_hest_get_next(section)) int ghes_notify_sea(void); +int ghes_notify_se
[PATCH v10 0/5] set VSESR_EL2 by user space and support NOTIFY_SEI notification
1. Detect whether KVM can set set guest SError syndrome 2. Support to Set VSESR_EL2 and inject SError by user space. 3. Support live migration to keep SError pending state and VSESR_EL2 value. 4. ACPI 6.1 adds support for NOTIFY_SEI as a GHES notification mechanism, so support this notification in software, KVM or kernel ARCH code call handle_guest_sei() to let ACP driver to handle this notification. Dongjiu Geng (5): arm64: KVM: Prepare set virtual SEI syndrome value arm64: KVM: export the capability to set guest SError syndrome arm/arm64: KVM: Introduce set and get per-vcpu event ACPI / APEI: Add SEI notification type support for ARMv8 arm64: handle NOTIFY_SEI notification by the APEI driver Documentation/virtual/kvm/api.txt| 37 +++-- arch/arm/include/asm/kvm_host.h | 6 arch/arm/kvm/guest.c | 12 arch/arm64/include/asm/kvm_emulate.h | 5 arch/arm64/include/asm/kvm_host.h| 7 + arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/include/uapi/asm/kvm.h| 10 +++ arch/arm64/kernel/traps.c| 4 +++ arch/arm64/kvm/guest.c | 26 ++ arch/arm64/kvm/inject_fault.c| 5 arch/arm64/kvm/reset.c | 4 +++ arch/arm64/mm/fault.c| 10 +++ drivers/acpi/apei/Kconfig| 15 ++ drivers/acpi/apei/ghes.c | 53 include/acpi/ghes.h | 1 + include/uapi/linux/kvm.h | 1 + virt/kvm/arm/arm.c | 18 17 files changed, 213 insertions(+), 2 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] arm64: rename the function arm64_is_ras_serror() to avoid confusion
The RAS SError Syndrome can be Implementation-Defined, arm64_is_ras_serror() is used to judge whether it is RAS SError, but arm64_is_ras_serror() does not include this judgement. In order to avoid function name confusion, we rename the arm64_is_ras_serror() to arm64_is_categorized_ras_serror(), this function is used to judge whether it is categorized RAS Serror. Change some code notes, unrecoverable RAS errors is imprecise, but Recoverable RAS errors is precise. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/traps.h | 20 arch/arm64/kernel/traps.c | 9 + arch/arm64/kvm/handle_exit.c | 3 ++- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/arch/arm64/include/asm/traps.h b/arch/arm64/include/asm/traps.h index 178e338..2a02b64 100644 --- a/arch/arm64/include/asm/traps.h +++ b/arch/arm64/include/asm/traps.h @@ -72,18 +72,23 @@ static inline int in_entry_text(unsigned long ptr) * CPUs with the RAS extensions have an Implementation-Defined-Syndrome bit * to indicate whether this ESR has a RAS encoding. CPUs without this feature * have a ISS-Valid bit in the same position. - * If this bit is set, we know its not a RAS SError. + * If this bit is set, we know it is not a categorized RAS SError. * If its clear, we need to know if the CPU supports RAS. Uncategorized RAS * errors share the same encoding as an all-zeros encoding from a CPU that * doesn't support RAS. */ -static inline bool arm64_is_ras_serror(u32 esr) +static inline bool arm64_is_categorized_ras_serror(u32 esr) { WARN_ON(preemptible()); + /* This is Implementation-Defined Syndrome */ if (esr & ESR_ELx_IDS) return false; + if ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR) + /* No severity information : Uncategorized */ + return false; + if (this_cpu_has_cap(ARM64_HAS_RAS_EXTN)) return true; else @@ -101,20 +106,11 @@ static inline u32 arm64_ras_serror_get_severity(u32 esr) { u32 aet = esr & ESR_ELx_AET; - if (!arm64_is_ras_serror(esr)) { + if (!arm64_is_categorized_ras_serror(esr)) { /* Not a RAS error, we can't interpret the ESR. */ return ESR_ELx_AET_UC; } - /* -* AET is RES0 if 'the value returned in the DFSC field is not -* [ESR_ELx_FSC_SERROR]' -*/ - if ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR) { - /* No severity information : Uncategorized */ - return ESR_ELx_AET_UC; - } - return aet; } diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c index bbb0fde..e88096a 100644 --- a/arch/arm64/kernel/traps.c +++ b/arch/arm64/kernel/traps.c @@ -689,12 +689,12 @@ bool arm64_is_fatal_ras_serror(struct pt_regs *regs, unsigned int esr) * a more severe error. */ return false; - + /* The exception has been imprecise */ case ESR_ELx_AET_UEU: /* Uncorrected Unrecoverable */ + /* The exception is precise */ case ESR_ELx_AET_UER: /* Uncorrected Recoverable */ /* -* The CPU can't make progress. The exception may have -* been imprecise. +* The CPU can't make progress. */ return true; @@ -710,7 +710,8 @@ asmlinkage void do_serror(struct pt_regs *regs, unsigned int esr) nmi_enter(); /* non-RAS errors are not containable */ - if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(regs, esr)) + if (!arm64_is_categorized_ras_serror(esr) || + arm64_is_fatal_ras_serror(regs, esr)) arm64_serror_panic(regs, esr); nmi_exit(); diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index e5e741b..913c19e 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -40,7 +40,8 @@ static void kvm_handle_guest_serror(struct kvm_vcpu *vcpu, u32 esr) { - if (!arm64_is_ras_serror(esr) || arm64_is_fatal_ras_serror(NULL, esr)) + if (!arm64_is_categorized_ras_serror(esr) || + arm64_is_fatal_ras_serror(NULL, esr)) kvm_inject_vabt(vcpu); } -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v9 3/7] acpi: apei: Add SEI notification type support for ARMv8
ARMv8.2 requires implementation of the RAS extension. In this extension, it adds SEI(SError Interrupt) notification type, this patch adds new GHES error source SEI handling functions. This error source parsing and handling method is similar with the SEA. Expose API ghes_notify_sei() to external users. External modules can call this exposed API to parse APEI table and handle the SEI notification. Signed-off-by: Dongjiu Geng --- drivers/acpi/apei/Kconfig | 15 ++ drivers/acpi/apei/ghes.c | 53 +++ include/acpi/ghes.h | 1 + 3 files changed, 69 insertions(+) diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 52ae543..ff4afc3 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -55,6 +55,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI SError(System Error) Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (SError interrupt). + + SEI happens with asynchronous external abort for errors on device + memory reads on ARMv8 systems. If a system supports firmware first + handling of SEI, the platform analyzes and handles hardware error + notifications from SEI, and it may then form a hardware error record for + the OS to parse and handle. This option allows the OS to look for + such hardware error record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 6a3f824..67cd3a7 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -855,6 +855,46 @@ static inline void ghes_sea_add(struct ghes *ghes) { } static inline void ghes_sea_remove(struct ghes *ghes) { } #endif /* CONFIG_ACPI_APEI_SEA */ +#ifdef CONFIG_ACPI_APEI_SEI +static LIST_HEAD(ghes_sei); + +/* + * Return 0 only if one of the SEI error sources successfully reported an error + * record sent from the firmware. + */ +int ghes_notify_sei(void) +{ + struct ghes *ghes; + int ret = -ENOENT; + + rcu_read_lock(); + list_for_each_entry_rcu(ghes, &ghes_sei, list) { + if (!ghes_proc(ghes)) + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +static void ghes_sei_add(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); +} + +static void ghes_sei_remove(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_del_rcu(&ghes->list); + mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); +} +#else /* CONFIG_ACPI_APEI_SEI */ +static inline void ghes_sei_add(struct ghes *ghes) { } +static inline void ghes_sei_remove(struct ghes *ghes) { } +#endif /* CONFIG_ACPI_APEI_SEI */ + #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* * printk is not safe in NMI context. So in NMI handler, we allocate @@ -1086,6 +1126,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1158,6 +1205,9 @@ static int ghes_probe(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_add(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_add(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); break; @@ -1211,6 +1261,9 @@ static int ghes_remove(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_remove(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_remove(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); break; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c8..9ba59e2 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -120,5 +120,6 @@ s
[PATCH v9 5/7] arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl
The ARM64 RAS SError Interrupt(SEI) syndrome value is specific to the guest and user space needs a way to tell KVM this value. So we add a new ioctl. Before user space specifies the Exception Syndrome Register ESR(ESR), it firstly checks that whether KVM has the capability to set the guest ESR, If has, will set it. Otherwise, nothing to do. For this ESR specifying, Only support for AArch64, not support AArch32. Signed-off-by: Dongjiu Geng --- change the name to KVM_CAP_ARM_INJECT_SERROR_ESR instead of X_ARM_RAS_EXTENSION, suggested here https://patchwork.kernel.org/patch/9925203/ --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 + arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/guest.c| 5 + arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 3 +++ virt/kvm/arm/arm.c| 7 +++ 8 files changed, 40 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e63a35f..6dfb9fc 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4347,3 +4347,14 @@ This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr. Its value is used to denote the target vcpu for a SynIC interrupt. For compatibilty, KVM initializes this msr to KVM's internal vcpu index. When this capability is absent, userspace can still query this msr's value. + +8.13 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify syndrome value reported to +guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +into ISS filed of ESR_EL1 diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 4a879f6..6cf5c7b 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,7 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome); unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..1e15fa2 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,15 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +/* + * we only support guest SError syndrome specifying + * for ARM64, not support it for ARM32. + */ +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index e923b58..769cc58 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -317,6 +317,7 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome); #define KVM_ARCH_WANT_MMU_NOTIFIER int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 5c7f657..738ae90 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -277,6 +277,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { unsigned long implementor = read_cpuid_implementor(); diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..38c8a64 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 7e9..0c861c4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -931,6 +931,7 @@ struct kvm_ppc_
[PATCH v9 4/7] KVM: arm64: Trap RAS error registers and set HCR_EL2's TERR & TEA
ARMv8.2 adds a new bit HCR_EL2.TEA which routes synchronous external aborts to EL2, and adds a trap control bit HCR_EL2.TERR which traps all Non-secure EL1&0 error record accesses to EL2. This patch enables the two bits for the guest OS, guaranteeing that KVM takes external aborts and traps attempts to access the physical error registers. ERRIDR_EL1 advertises the number of error records, we return zero meaning we can treat all the other registers as RAZ/WI too. Signed-off-by: Dongjiu Geng [removed specific emulation, use trap_raz_wi() directly for everything, rephrased parts of the commit message] Signed-off-by: James Morse --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ arch/arm64/include/asm/sysreg.h | 10 ++ arch/arm64/kvm/sys_regs.c| 10 ++ 4 files changed, 29 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..1188272 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fc..555b28b 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 64e2a80..47b967d 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -169,6 +169,16 @@ #define SYS_AFSR0_EL1 sys_reg(3, 0, 5, 1, 0) #define SYS_AFSR1_EL1 sys_reg(3, 0, 5, 1, 1) #define SYS_ESR_EL1sys_reg(3, 0, 5, 2, 0) + +#define SYS_ERRIDR_EL1 sys_reg(3, 0, 5, 3, 0) +#define SYS_ERRSELR_EL1sys_reg(3, 0, 5, 3, 1) +#define SYS_ERXFR_EL1 sys_reg(3, 0, 5, 4, 0) +#define SYS_ERXCTLR_EL1sys_reg(3, 0, 5, 4, 1) +#define SYS_ERXSTATUS_EL1 sys_reg(3, 0, 5, 4, 2) +#define SYS_ERXADDR_EL1sys_reg(3, 0, 5, 4, 3) +#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0) +#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1) + #define SYS_FAR_EL1sys_reg(3, 0, 6, 0, 0) #define SYS_PAR_EL1sys_reg(3, 0, 7, 4, 0) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2e070d3..2b1fafa 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -953,6 +953,16 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu, { SYS_DESC(SYS_AFSR0_EL1), access_vm_reg, reset_unknown, AFSR0_EL1 }, { SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 }, { SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 }, + + { SYS_DESC(SYS_ERRIDR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERRSELR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXFR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXCTLR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXSTATUS_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXADDR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi }, + { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v9 2/7] KVM: arm64: Save ESR_EL2 on guest SError
From: James Morse When we exit a guest due to an SError the vcpu fault info isn't updated with the ESR. Today this is only done for traps. The v8.2 RAS Extensions define ISS values for SError. Update the vcpu's fault_info with the ESR on SError so that handle_exit() can determine if this was a RAS SError and decode its severity. Signed-off-by: James Morse --- arch/arm64/kvm/hyp/switch.c | 9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 945e79c..fb5a538 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -228,11 +228,12 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) { - u64 esr = read_sysreg_el2(esr); - u8 ec = ESR_ELx_EC(esr); + u8 ec; + u64 esr; u64 hpfar, far; - vcpu->arch.fault.esr_el2 = esr; + esr = vcpu->arch.fault.esr_el2; + ec = ESR_ELx_EC(esr); if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) return true; @@ -313,6 +314,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) exit_code = __guest_enter(vcpu, host_ctxt); /* And we're baaack! */ + if (ARM_EXCEPTION_CODE(exit_code) != ARM_EXCEPTION_IRQ) + vcpu->arch.fault.esr_el2 = read_sysreg_el2(esr); /* * 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 -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v9 6/7] arm64: kvm: Set Virtual SError Exception Syndrome for guest
RAS Extension add a VSESR_EL2 register which can provide the syndrome value reported to software on taking a virtual SError interrupt exception. This patch supports to specify this Syndrome. In the RAS Extensions we can not set all-zero syndrome value for SError, which means 'RAS error: Uncategorized' instead of 'no valid ISS'. So set it to IMPLEMENTATION DEFINED syndrome by default. We also need to support userspace to specify a valid syndrome value, Because in some case, the recovery is driven by userspace. This patch can support that userspace specify it. In the guest/host world switch, restore this value to VSESR_EL2 only when HCR_EL2.VSE is set. This value no need to be saved because it is stale vale when guest exit. Signed-off-by: Dongjiu Geng [Set an impdef ESR for Virtual-SError] Signed-off-by: James Morse --- arch/arm64/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_host.h| 1 + arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kvm/guest.c | 11 ++- arch/arm64/kvm/hyp/switch.c | 16 arch/arm64/kvm/inject_fault.c| 13 - 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 555b28b..73c84d0 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault.vsesr_el2; +} + +static inline void kvm_vcpu_set_vsesr(struct kvm_vcpu *vcpu, unsigned long val) +{ + vcpu->arch.fault.vsesr_el2 = val; +} + static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 769cc58..53d1d81 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -88,6 +88,7 @@ struct kvm_vcpu_fault_info { u32 esr_el2;/* Hyp Syndrom Register */ u64 far_el2;/* Hyp Fault Address Register */ u64 hpfar_el2; /* Hyp IPA Fault Address Register */ + u32 vsesr_el2; /* Virtual SError Exception Syndrome Register */ }; /* diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 47b967d..3b035cc 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -86,6 +86,9 @@ #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) #define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3) +/* virtual SError exception syndrome register */ +#define REG_VSESR_EL2 sys_reg(3, 4, 5, 2, 3) + #define SET_PSTATE_PAN(x) __emit_inst(0xd500 | REG_PSTATE_PAN_IMM | \ (!!x)<<8 | 0x1f) #define SET_PSTATE_UAO(x) __emit_inst(0xd500 | REG_PSTATE_UAO_IMM | \ diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 738ae90..ffad42b 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -279,7 +279,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) { - return -EINVAL; + u64 reg = *syndrome; + + /* inject virtual system Error or asynchronous abort */ + kvm_inject_vabt(vcpu); + + if (reg) + /* set vsesr_el2[24:0] with value that user space specified */ + kvm_vcpu_set_vsesr(vcpu, reg & ESR_ELx_ISS_MASK); + + return 0; } int __attribute_const__ kvm_target_cpu(void) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index fb5a538..7f08a5d 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -67,6 +67,14 @@ static hyp_alternate_select(__activate_traps_arch, __activate_traps_nvhe, __activate_traps_vhe, ARM64_HAS_VIRT_HOST_EXTN); +static void __hyp_text __sysreg_set_vsesr(struct kvm_vcpu *vcpu, u64 value) +{ + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN) && + (value & HCR_VSE)) + write_sysreg_s(kvm_vcpu_get_vsesr(vcpu), REG_VSESR_EL2); +} + + static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) { u64 val; @@ -86,6 +94,14 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) isb(); } write_sysreg(val, hcr_el2); + + /* +* If the virtual SError interrupt is taken to EL1 using AArch64, +* then VSESR_EL2 provides the syndrome value reported in ISS field +* of ESR_EL1. +*/ + __sysreg_set_vsesr(vcpu, val); + /* Trap on AArch32 cp15 c15 accesses (EL
[PATCH v9 0/7] Handle guest RAS Error in KVM and kernel
This series patches mainly do below things: 1. Trap guest RAS ERR* registers accesses to EL2 from Non-secure EL1, KVM will will do a minimum simulation, these registers are simulated to RAZ/WI in KVM. 2. Route guest synchronous External Abort to EL2. If it is also routed to EL3 by firmware at the same time, system will trap to EL3 firmware instead of EL2 KVM, then firmware judges whether EL2 routing is enabled, if enabled, jump back to EL2 KVM, otherwise jump back to EL1 host kernel. 3. Enable APEI ARv8 SEI notification to parse the CPER records for SError in the ACPI GHES driver, KVM will call handle_guest_sei() to let ACPI driver to parse the CPER recorded for SError which happened in the guest 4. If ACPI driver parsed the CPER record failed, KVM will classify the Error through Exception Syndrome Register and do different approaches according to Asynchronous Error Type 5. If the guest RAS SError is not propagated and not consumed, this exception is precise, we temporarily shut down the VM to isolate the error. For other Asynchronous Error Type, KVM directly injects virtual SError with IMPLEMENTATION DEFINED ESR or KVM panic if the error is fatal. For the RAS extension, guest virtual ESR must be set, because all-zero means 'RAS error: Uncategorized' instead of 'no valid ISS', so set this ESR to IMPLEMENTATION DEFINED by default if user space does not specify it. change since v8: 1. update the patch [1/7] and [2/7] to align this serie. https://www.spinics.net/lists/arm-kernel/msg623513.html https://www.spinics.net/lists/arm-kernel/msg623520.html 2. In kvm ,check handle_guest_sei()'s return value. If this function return true, stop classifying errors. 3. Temporarily shut down the VM to isolate the error for recoverable error (UER) 4. update some patch's commit messages and clean some patches Dongjiu Geng (5): acpi: apei: Add SEI notification type support for ARMv8 KVM: arm64: Trap RAS error registers and set HCR_EL2's TERR & TEA arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl arm64: kvm: Set Virtual SError Exception Syndrome for guest arm64: kvm: handle guest SError Interrupt by categorization James Morse (1): KVM: arm64: Save ESR_EL2 on guest SError Xie XiuQi (1): arm64: cpufeature: Detect CPU RAS Extentions Documentation/virtual/kvm/api.txt| 11 ++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 + arch/arm64/Kconfig | 16 + arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/esr.h | 11 ++ arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 17 + arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 15 arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/cpufeature.c | 13 +++ arch/arm64/kvm/guest.c | 14 arch/arm64/kvm/handle_exit.c | 68 +--- arch/arm64/kvm/hyp/switch.c | 25 +++-- arch/arm64/kvm/inject_fault.c| 13 ++- arch/arm64/kvm/reset.c | 3 ++ arch/arm64/kvm/sys_regs.c| 10 ++ arch/arm64/mm/fault.c| 16 + drivers/acpi/apei/Kconfig| 15 drivers/acpi/apei/ghes.c | 53 include/acpi/ghes.h | 1 + include/uapi/linux/kvm.h | 3 ++ virt/kvm/arm/arm.c | 7 24 files changed, 320 insertions(+), 9 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v9 7/7] arm64: kvm: handle guest SError Interrupt by categorization
If it is not RAS SError, directly inject virtual SError, which will keep the old way, otherwise firstly let host ACPI kernel driver to handle it. If the ACPI handling is failed, KVM continues categorizing errors by the ESR_ELx. For the recoverable error (UER), it has not been silently propagated and has not (yet) been architecturally consumed by the PE, the exception is precise. In order to make it simple, we temporarily shut down the VM to isolate the error. Signed-off-by: Dongjiu Geng --- change since v8: 1. Check handle_guest_sei()'s return value 2. Temporarily shut down the VM to isolate the error for the recoverable error (UER) 3. Remove some unused macro definitions --- arch/arm64/include/asm/esr.h | 11 ++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/handle_exit.c | 68 +--- arch/arm64/mm/fault.c| 16 + 4 files changed, 92 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 66ed8b6..a751e86 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -102,6 +102,7 @@ #define ESR_ELx_FSC_ACCESS (0x08) #define ESR_ELx_FSC_FAULT (0x04) #define ESR_ELx_FSC_PERM (0x0C) +#define ESR_ELx_FSC_SERROR (0x11) /* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV_SHIFT (24) @@ -119,6 +120,16 @@ #define ESR_ELx_CM_SHIFT (8) #define ESR_ELx_CM (UL(1) << ESR_ELx_CM_SHIFT) +/* ISS field definitions for SError interrupt */ +#define ESR_ELx_AET_SHIFT (10) +#define ESR_ELx_AET(UL(0x7) << ESR_ELx_AET_SHIFT) +/* Restartable error */ +#define ESR_ELx_AET_UEO(UL(2) << ESR_ELx_AET_SHIFT) +/* Recoverable error */ +#define ESR_ELx_AET_UER(UL(3) << ESR_ELx_AET_SHIFT) +/* Corrected error */ +#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT) + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..9ee13ad 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 7debb74..5b806d4 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -178,6 +179,67 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) return arm_exit_handlers[hsr_ec]; } +/** + * kvm_handle_guest_sei - handles SError interrupt or asynchronous aborts + * @vcpu: the VCPU pointer + * @run:access to the kvm_run structure for results + * + * For RAS SError interrupt, firstly let host kernel handle it. If handling + * failed, then categorize the error by the ESR + */ +static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned int esr = kvm_vcpu_get_hsr(vcpu); + bool impdef_syndrome = esr & ESR_ELx_ISV; /* aka IDS */ + unsigned int aet = esr & ESR_ELx_AET; + + /* +* This is not RAS SError +*/ + if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + kvm_inject_vabt(vcpu); + return 1; + } + + /* For RAS the host kernel may handle this abort. */ + if (!handle_guest_sei()) + return 1; + + /* +* In below two conditions, it will directly inject the +* virtual SError: +* 1. The Syndrome is IMPLEMENTATION DEFINED +* 2. It is Uncategorized SEI +*/ + if (impdef_syndrome || + ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR)) { + kvm_inject_vabt(vcpu); + return 1; + } + + switch (aet) { + case ESR_ELx_AET_CE:/* corrected error */ + case ESR_ELx_AET_UEO: /* restartable error, not yet consumed */ + return 1; /* continue processing the guest exit */ + case ESR_ELx_AET_UER: /* recoverable error */ + /* +* the exception is precise, not been silently propagated +* and not been consumed by the CPU, temporarily shut down +* the VM to isolated the error, hope not touch it again. +*/ + run->exit_reason = KVM_EXIT_EXCEPTION; + return 0; + default: + /* +* Until now, the CPU supports RAS, SError interrupt is
[PATCH v9 1/7] arm64: cpufeature: Detect CPU RAS Extentions
From: Xie XiuQi ARM's v8.2 Extentions add support for Reliability, Availability and Serviceability (RAS). On CPUs with these extensions system software can use additional barriers to isolate errors and determine if faults are pending. Add cpufeature detection and a barrier in the context-switch code. There is no need to use alternatives for this as CPUs that don't support this feature will treat the instruction as a nop. Platform level RAS support may require additional firmware support. Signed-off-by: Xie XiuQi [Rebased added config option, reworded commit message] Signed-off-by: James Morse Signed-off-by: Dongjiu Geng Reviewed-by: Catalin Marinas --- arch/arm64/Kconfig | 16 arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kernel/cpufeature.c | 13 + 4 files changed, 33 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0df64a6..cc00d10 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -973,6 +973,22 @@ config ARM64_PMEM operations if DC CVAP is not supported (following the behaviour of DC CVAP itself if the system does not define a point of persistence). +config ARM64_RAS_EXTN + bool "Enable support for RAS CPU Extensions" + default y + help + CPUs that support the Reliability, Availability and Serviceability + (RAS) Extensions, part of ARMv8.2 are able to track faults and + errors, classify them and report them to software. + + On CPUs with these extensions system software can use additional + barriers to determine if faults are pending and read the + classification from a new set of registers. + + Selecting this feature will allow the kernel to use these barriers + and access the new registers if the system supports the extension. + Platform RAS features may additionally depend on firmware support. + endmenu config ARM64_MODULE_CMODEL_LARGE diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 8da6216..4820d44 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -40,7 +40,8 @@ #define ARM64_WORKAROUND_85892119 #define ARM64_WORKAROUND_CAVIUM_30115 20 #define ARM64_HAS_DCPOP21 +#define ARM64_HAS_RAS_EXTN 22 -#define ARM64_NCAPS22 +#define ARM64_NCAPS23 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index f707fed..64e2a80 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -332,6 +332,7 @@ #define ID_AA64ISAR1_DPB_SHIFT 0 /* id_aa64pfr0 */ +#define ID_AA64PFR0_RAS_SHIFT 28 #define ID_AA64PFR0_GIC_SHIFT 24 #define ID_AA64PFR0_ASIMD_SHIFT20 #define ID_AA64PFR0_FP_SHIFT 16 @@ -340,6 +341,7 @@ #define ID_AA64PFR0_EL1_SHIFT 4 #define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_RAS_V1 0x1 #define ID_AA64PFR0_FP_NI 0xf #define ID_AA64PFR0_FP_SUPPORTED 0x0 #define ID_AA64PFR0_ASIMD_NI 0xf diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 21e2c95..4846974 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -125,6 +125,7 @@ static int __init register_cpu_hwcaps_dumper(void) }; static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_RAS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), @@ -900,6 +901,18 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus .min_field_value = 1, }, #endif +#ifdef CONFIG_ARM64_RAS_EXTN + { + .desc = "RAS Extension Support", + .capability = ARM64_HAS_RAS_EXTN, + .def_scope = SCOPE_SYSTEM, + .matches = has_cpuid_feature, + .sys_reg = SYS_ID_AA64PFR0_EL1, + .sign = FTR_UNSIGNED, + .field_pos = ID_AA64PFR0_RAS_SHIFT, + .min_field_value = ID_AA64PFR0_RAS_V1, + }, +#endif /* CONFIG_ARM64_RAS_EXTN */ {}, }; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] KVM: arm64: handle the translation table walk RAS error
For the RAS Synchronous External Abort, there are two types. One is memory access, it will be handled by host APEI driver. Another is translation table walk, in essence, it is hardware memory error on stage1 or stage2 page table. For the guest stage1 translation table error, if host APEI driver handles it, APEI driver will unmap this page for the stage1 page table, then switch to guest, guest reused this page table and generate stage2 data abort, KVM deliver SIGBUS to user space. User space inject this error to guest, when guest handle this abort, it may also use this stage1 page table, but it already unmap by host APEI driver, then generate stage2 data abort again, so this will lead to dead loop. For the guest stage2 translation table error, if host APEI driver handles it, it will do nothing. So for above reasons, we directly inject this Synchronous External Abort to guest and let guest handle it, for example, kill the guest application or panic guest OS. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ virt/kvm/arm/mmu.c | 14 -- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 1188272..b8cb67a 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -217,6 +217,8 @@ #define FSC_SECC_TTW2 (0x1e) #define FSC_SECC_TTW3 (0x1f) +#define FSC_SEA_TTWFSC_SEA_TTW0 + /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ #define HPFAR_MASK (~UL(0xf)) diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index b36945d..6eab82d 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1484,8 +1484,18 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu, struct kvm_run *run) /* Synchronous External Abort? */ if (kvm_vcpu_dabt_isextabt(vcpu)) { /* -* For RAS the host kernel may handle this abort. -* There is no need to pass the error into the guest. +* For RAS translation table walk abort, pass the error +* into the guest. +*/ + if (fault_status == FSC_SEA_TTW) { + kvm_inject_dabt(vcpu, kvm_vcpu_get_hfar(vcpu)); + return 1; + } + + /* +* For RAS normal memory access abort, the host kernel may +* handle this abort. There is no need to pass the error into +* the guest. */ if (!handle_guest_sea(fault_ipa, kvm_vcpu_get_hsr(vcpu))) return 1; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 7/7] arm64: kvm: handle SError Interrupt by categorization
If it is not RAS SError, directly inject virtual SError, which will keep the old way. If it is RAS SError, firstly let host ACPI module to handle it. For the ACPI handling, if the error address is invalid, APEI driver will not identify the address to hwpoison memory and can not notify guest to do the recovery. In order to safe, KVM continues categorizing errors and handle it separately. If the RAS error is not propagated, let host user space to handle it. The reason is that sometimes we can only kill the guest effected application instead of panic whose guest OS. Host user space specifies a valid ESR and inject virtual SError, guest can just kill the current application if the non-consumed error coming from guest application. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/asm/esr.h | 15 arch/arm64/include/asm/kvm_asm.h | 3 ++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/handle_exit.c | 67 +--- arch/arm64/mm/fault.c| 16 + 5 files changed, 98 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 66ed8b6..aca7eee 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -102,6 +102,7 @@ #define ESR_ELx_FSC_ACCESS (0x08) #define ESR_ELx_FSC_FAULT (0x04) #define ESR_ELx_FSC_PERM (0x0C) +#define ESR_ELx_FSC_SERROR (0x11) /* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV_SHIFT (24) @@ -119,6 +120,20 @@ #define ESR_ELx_CM_SHIFT (8) #define ESR_ELx_CM (UL(1) << ESR_ELx_CM_SHIFT) +/* ISS field definitions for SError interrupt */ +#define ESR_ELx_AET_SHIFT (10) +#define ESR_ELx_AET(UL(0x7) << ESR_ELx_AET_SHIFT) +/* Uncontainable error */ +#define ESR_ELx_AET_UC (UL(0) << ESR_ELx_AET_SHIFT) +/* Unrecoverable error */ +#define ESR_ELx_AET_UEU(UL(1) << ESR_ELx_AET_SHIFT) +/* Restartable error */ +#define ESR_ELx_AET_UEO(UL(2) << ESR_ELx_AET_SHIFT) +/* Recoverable error */ +#define ESR_ELx_AET_UER(UL(3) << ESR_ELx_AET_SHIFT) +/* Corrected */ +#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT) + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 26a64d0..884f723 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -27,6 +27,9 @@ #define ARM_EXCEPTION_IRQ0 #define ARM_EXCEPTION_EL1_SERROR 1 #define ARM_EXCEPTION_TRAP 2 +/* Error code for SError Interrupt (SEI) exception */ +#define KVM_SEI_SEV_RECOVERABLE 1 + /* The hyp-stub will return this for any kvm_call_hyp() call */ #define ARM_EXCEPTION_HYP_GONE HVC_STUB_ERR diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..9ee13ad 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ void hook_debug_fault_code(int nr, int (*fn)(unsigned long, unsigned int, }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 7debb74..1afdc87 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -178,6 +179,66 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) return arm_exit_handlers[hsr_ec]; } +/** + * kvm_handle_guest_sei - handles SError interrupt or asynchronous aborts + * @vcpu: the VCPU pointer + * + * For RAS SError interrupt, firstly let host kernel handle it. + * If the AET is [ESR_ELx_AET_UER], then let user space handle it, + */ +static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned int esr = kvm_vcpu_get_hsr(vcpu); + bool impdef_syndrome = esr & ESR_ELx_ISV; /* aka IDS */ + unsigned int aet = esr & ESR_ELx_AET; + + /* +* This is not RAS SError +*/ + if (!cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + kvm_inject_vabt(vcpu); + return 1; + } + + /* The host kernel may handle this abort. */ + handle_guest_sei(); + + /* +* In below two conditions, it will directly inject the +* virtual SError: +* 1. The Syndrome is IMPLEMENTATION DEFINED +* 2. It is Uncategorized SEI +*/ + if (impdef_syndrome || + ((esr & ESR_ELx_FSC) != ESR_ELx_FSC_SERROR)) { + kvm_inject_vabt(vcpu); +
[PATCH v8 0/7] Support RAS virtualization in KVM
This series patches mainly do below things: 1. Trap RAS ERR* registers Accesses to EL2 from Non-secure EL1, KVM will will do a minimum simulation, there registers are simulated to RAZ/WI in KVM. 2. Route synchronous External Abort exceptions from Non-secure EL0 and EL1 to EL2. When exception EL3 routing is enabled by firmware, system will trap to EL3 firmware instead of EL2 KVM, then firmware judges whether El2 routing is enabled, if enabled, jump to EL2 KVM, otherwise jump to EL1 host kernel. 3. Enable APEI ARv8 SEI notification to parse the CPER records for SError in the ACPI GHES driver, KVM will call handle_guest_sei() to let ACPI driver to parse the CPER record for SError which happened in the guest 4. Although we can use APEI driver to handle the guest SError, but not all system support SEI notification, such as kernel-first. So here KVM will also classify the Error through Exception Syndrome Register and do different approaches according to Asynchronous Error Type 5. If the guest SError error is not propagated and not consumed, then KVM return recoverable error status to user-space, user-space will specify the guest ESR and inject a virtual SError. For other Asynchronous Error Type, KVM directly injects virtual SError with IMPLEMENTATION DEFINED ESR or KVM is panic if the error is fatal. In the RAS extension, guest virtual ESR must be set, because all-zero means 'RAS error: Uncategorized' instead of 'no valid ISS', so set this ESR to IMPLEMENTATION DEFINED by default if user space does not specify it. Dongjiu Geng (5): acpi: apei: Add SEI notification type support for ARMv8 KVM: arm64: Trap RAS error registers and set HCR_EL2's TERR & TEA arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl arm64: kvm: Set Virtual SError Exception Syndrome for guest arm64: kvm: handle SError Interrupt by categorization James Morse (1): KVM: arm64: Save ESR_EL2 on guest SError Xie XiuQi (1): arm64: cpufeature: Detect CPU RAS Extentions Documentation/virtual/kvm/api.txt| 11 ++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 + arch/arm64/Kconfig | 16 + arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/esr.h | 15 arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_asm.h | 3 ++ arch/arm64/include/asm/kvm_emulate.h | 17 + arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 15 arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kernel/cpufeature.c | 13 +++ arch/arm64/kernel/process.c | 3 ++ arch/arm64/kvm/guest.c | 14 arch/arm64/kvm/handle_exit.c | 67 +--- arch/arm64/kvm/hyp/switch.c | 31 +++-- arch/arm64/kvm/inject_fault.c| 13 ++- arch/arm64/kvm/reset.c | 3 ++ arch/arm64/kvm/sys_regs.c| 10 ++ arch/arm64/mm/fault.c| 16 + drivers/acpi/apei/Kconfig| 15 drivers/acpi/apei/ghes.c | 53 include/acpi/ghes.h | 1 + include/uapi/linux/kvm.h | 3 ++ virt/kvm/arm/arm.c | 7 27 files changed, 336 insertions(+), 9 deletions(-) -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 6/7] arm64: kvm: Set Virtual SError Exception Syndrome for guest
RAS Extension add a VSESR_EL2 register which can provides the syndrome value reported to software on taking a virtual SError interrupt exception. This patch supports to specify this Syndrome. In the RAS Extensions we can not set all-zero syndrome value for SError, which means 'RAS error: Uncategorized' instead of 'no valid ISS'. So set it to IMPLEMENTATION DEFINED syndrome by default. We also need to support userspace to specify a valid syndrome value, Because in some case, the recovery is driven by userspace. This patch can support that userspace can specify it. In the guest/host world switch, restore this value to VSESR_EL2 only when HCR_EL2.VSE is set. This value no need to be saved because it is stale vale when guest exit. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu [Set an impdef ESR for Virtual-SError] Signed-off-by: James Morse --- arch/arm64/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_host.h| 1 + arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kvm/guest.c | 11 ++- arch/arm64/kvm/hyp/switch.c | 16 arch/arm64/kvm/inject_fault.c| 13 - 6 files changed, 52 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 555b28b..73c84d0 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault.vsesr_el2; +} + +static inline void kvm_vcpu_set_vsesr(struct kvm_vcpu *vcpu, unsigned long val) +{ + vcpu->arch.fault.vsesr_el2 = val; +} + static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 769cc58..53d1d81 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -88,6 +88,7 @@ struct kvm_vcpu_fault_info { u32 esr_el2;/* Hyp Syndrom Register */ u64 far_el2;/* Hyp Fault Address Register */ u64 hpfar_el2; /* Hyp IPA Fault Address Register */ + u32 vsesr_el2; /* Virtual SError Exception Syndrome Register */ }; /* diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 47b967d..3b035cc 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -86,6 +86,9 @@ #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) #define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3) +/* virtual SError exception syndrome register */ +#define REG_VSESR_EL2 sys_reg(3, 4, 5, 2, 3) + #define SET_PSTATE_PAN(x) __emit_inst(0xd500 | REG_PSTATE_PAN_IMM | \ (!!x)<<8 | 0x1f) #define SET_PSTATE_UAO(x) __emit_inst(0xd500 | REG_PSTATE_UAO_IMM | \ diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 738ae90..ffad42b 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -279,7 +279,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) { - return -EINVAL; + u64 reg = *syndrome; + + /* inject virtual system Error or asynchronous abort */ + kvm_inject_vabt(vcpu); + + if (reg) + /* set vsesr_el2[24:0] with value that user space specified */ + kvm_vcpu_set_vsesr(vcpu, reg & ESR_ELx_ISS_MASK); + + return 0; } int __attribute_const__ kvm_target_cpu(void) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index c6f17c7..06a71d2 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -67,6 +67,14 @@ static hyp_alternate_select(__activate_traps_arch, __activate_traps_nvhe, __activate_traps_vhe, ARM64_HAS_VIRT_HOST_EXTN); +static void __hyp_text __sysreg_set_vsesr(struct kvm_vcpu *vcpu, u64 value) +{ + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN) && + (value & HCR_VSE)) + write_sysreg_s(kvm_vcpu_get_vsesr(vcpu), REG_VSESR_EL2); +} + + static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) { u64 val; @@ -86,6 +94,14 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu) isb(); } write_sysreg(val, hcr_el2); + + /* +* If the virtual SError interrupt is taken to EL1 using AArch64, +* then VSESR_EL2 provides the syndrome value reported in ISS field +* of ESR_EL1. +*/ + __sysreg_set_vsesr(vcpu, val); +
[PATCH v8 5/7] arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl
The ARM64 RAS SError Interrupt(SEI) syndrome value is specific to the guest and user space needs a way to tell KVM this value. So we add a new ioctl. Before user space specifies the Exception Syndrome Register ESR(ESR), it firstly checks that whether KVM has the capability to set the guest ESR, If has, will set it. Otherwise, nothing to do. For this ESR specifying, Only support for AArch64, not support AArch32. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu change the name to KVM_CAP_ARM_INJECT_SERROR_ESR instead of X_ARM_RAS_EXTENSION, suggested here https://patchwork.kernel.org/patch/9925203/ --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 + arch/arm64/include/asm/kvm_host.h | 1 + arch/arm64/kvm/guest.c| 5 + arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 3 +++ virt/kvm/arm/arm.c| 7 +++ 8 files changed, 40 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e63a35f..6dfb9fc 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4347,3 +4347,14 @@ This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr. Its value is used to denote the target vcpu for a SynIC interrupt. For compatibilty, KVM initializes this msr to KVM's internal vcpu index. When this capability is absent, userspace can still query this msr's value. + +8.13 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify syndrome value reported to +guest OS when guest takes a virtual SError interrupt exception. +If KVM has this capability, userspace can only specify the ISS field for the ESR +syndrome, can not specify the EC field which is not under control by KVM. +If this virtual SError is taken to EL1 using AArch64, this value will be reported +into ISS filed of ESR_EL1 diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 4a879f6..6cf5c7b 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,7 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome); unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..1e15fa2 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,15 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +/* + * we only support guest SError syndrome specifying + * for ARM64, not support it for ARM32. + */ +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index e923b58..769cc58 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -317,6 +317,7 @@ struct kvm_vcpu_stat { int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome); #define KVM_ARCH_WANT_MMU_NOTIFIER int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 5c7f657..738ae90 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -277,6 +277,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u32 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { unsigned long implementor = read_cpuid_implementor(); diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..38c8a64 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_INJECT_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 7e9..0c861c4 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -931,6 +931,7
[PATCH v8 4/7] KVM: arm64: Trap RAS error registers and set HCR_EL2's TERR & TEA
ARMv8.2 adds a new bit HCR_EL2.TEA which routes synchronous external aborts to EL2, and adds a trap control bit HCR_EL2.TERR which traps all Non-secure EL1&0 error record accesses to EL2. This patch enables the two bits for the guest OS, guaranteeing that KVM takes external aborts and traps attempts to access the physical error registers. ERRIDR_EL1 advertises the number of error records, we return zero meaning we can treat all the other registers as RAZ/WI too. Signed-off-by: Dongjiu Geng [removed specific emulation, use trap_raz_wi() directly for everything, rephrased parts of the commit message] Signed-off-by: James Morse --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ arch/arm64/include/asm/sysreg.h | 10 ++ arch/arm64/kvm/sys_regs.c| 10 ++ 4 files changed, 29 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..1188272 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fc..555b28b 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 64e2a80..47b967d 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -169,6 +169,16 @@ #define SYS_AFSR0_EL1 sys_reg(3, 0, 5, 1, 0) #define SYS_AFSR1_EL1 sys_reg(3, 0, 5, 1, 1) #define SYS_ESR_EL1sys_reg(3, 0, 5, 2, 0) + +#define SYS_ERRIDR_EL1 sys_reg(3, 0, 5, 3, 0) +#define SYS_ERRSELR_EL1sys_reg(3, 0, 5, 3, 1) +#define SYS_ERXFR_EL1 sys_reg(3, 0, 5, 4, 0) +#define SYS_ERXCTLR_EL1sys_reg(3, 0, 5, 4, 1) +#define SYS_ERXSTATUS_EL1 sys_reg(3, 0, 5, 4, 2) +#define SYS_ERXADDR_EL1sys_reg(3, 0, 5, 4, 3) +#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0) +#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1) + #define SYS_FAR_EL1sys_reg(3, 0, 6, 0, 0) #define SYS_PAR_EL1sys_reg(3, 0, 7, 4, 0) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2e070d3..2b1fafa 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -953,6 +953,16 @@ static bool access_cntp_cval(struct kvm_vcpu *vcpu, { SYS_DESC(SYS_AFSR0_EL1), access_vm_reg, reset_unknown, AFSR0_EL1 }, { SYS_DESC(SYS_AFSR1_EL1), access_vm_reg, reset_unknown, AFSR1_EL1 }, { SYS_DESC(SYS_ESR_EL1), access_vm_reg, reset_unknown, ESR_EL1 }, + + { SYS_DESC(SYS_ERRIDR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERRSELR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXFR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXCTLR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXSTATUS_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXADDR_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXMISC0_EL1), trap_raz_wi }, + { SYS_DESC(SYS_ERXMISC1_EL1), trap_raz_wi }, + { SYS_DESC(SYS_FAR_EL1), access_vm_reg, reset_unknown, FAR_EL1 }, { SYS_DESC(SYS_PAR_EL1), NULL, reset_unknown, PAR_EL1 }, -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v8 3/7] acpi: apei: Add SEI notification type support for ARMv8
ARMv8.2 requires implementation of the RAS extension, in this extension it adds SEI(SError Interrupt) notification type, this patch adds new GHES error source SEI handling functions. This error source parsing and handling method is similar with the SEA. Expose API ghes_notify_sei() to external users. External modules can call this exposed API to parse APEI table and handle the SEI notification. Signed-off-by: Dongjiu Geng --- drivers/acpi/apei/Kconfig | 15 ++ drivers/acpi/apei/ghes.c | 53 +++ include/acpi/ghes.h | 1 + 3 files changed, 69 insertions(+) diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index 52ae543..ff4afc3 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -55,6 +55,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI SError(System Error) Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (SError interrupt). + + SEI happens with asynchronous external abort for errors on device + memory reads on ARMv8 systems. If a system supports firmware first + handling of SEI, the platform analyzes and handles hardware error + notifications from SEI, and it may then form a hardware error record for + the OS to parse and handle. This option allows the OS to look for + such hardware error record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index 6a3f824..67cd3a7 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -855,6 +855,46 @@ static inline void ghes_sea_add(struct ghes *ghes) { } static inline void ghes_sea_remove(struct ghes *ghes) { } #endif /* CONFIG_ACPI_APEI_SEA */ +#ifdef CONFIG_ACPI_APEI_SEI +static LIST_HEAD(ghes_sei); + +/* + * Return 0 only if one of the SEI error sources successfully reported an error + * record sent from the firmware. + */ +int ghes_notify_sei(void) +{ + struct ghes *ghes; + int ret = -ENOENT; + + rcu_read_lock(); + list_for_each_entry_rcu(ghes, &ghes_sei, list) { + if (!ghes_proc(ghes)) + ret = 0; + } + rcu_read_unlock(); + return ret; +} + +static void ghes_sei_add(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_add_rcu(&ghes->list, &ghes_sei); + mutex_unlock(&ghes_list_mutex); +} + +static void ghes_sei_remove(struct ghes *ghes) +{ + mutex_lock(&ghes_list_mutex); + list_del_rcu(&ghes->list); + mutex_unlock(&ghes_list_mutex); + synchronize_rcu(); +} +#else /* CONFIG_ACPI_APEI_SEI */ +static inline void ghes_sei_add(struct ghes *ghes) { } +static inline void ghes_sei_remove(struct ghes *ghes) { } +#endif /* CONFIG_ACPI_APEI_SEI */ + #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* * printk is not safe in NMI context. So in NMI handler, we allocate @@ -1086,6 +1126,13 @@ static int ghes_probe(struct platform_device *ghes_dev) goto err; } break; + case ACPI_HEST_NOTIFY_SEI: + if (!IS_ENABLED(CONFIG_ACPI_APEI_SEI)) { + pr_warn(GHES_PFX "Generic hardware error source: %d notified via SEI is not supported!\n", + generic->header.source_id); + goto err; + } + break; case ACPI_HEST_NOTIFY_NMI: if (!IS_ENABLED(CONFIG_HAVE_ACPI_APEI_NMI)) { pr_warn(GHES_PFX "Generic hardware error source: %d notified via NMI interrupt is not supported!\n", @@ -1158,6 +1205,9 @@ static int ghes_probe(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_add(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_add(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_add(ghes); break; @@ -1211,6 +1261,9 @@ static int ghes_remove(struct platform_device *ghes_dev) case ACPI_HEST_NOTIFY_SEA: ghes_sea_remove(ghes); break; + case ACPI_HEST_NOTIFY_SEI: + ghes_sei_remove(ghes); + break; case ACPI_HEST_NOTIFY_NMI: ghes_nmi_remove(ghes); break; diff --git a/include/acpi/ghes.h b/include/acpi/ghes.h index 8feb0c8..9ba59e2 100644 --- a/include/acpi/ghes.h +++ b/include/acpi/ghes.h @@ -120,5 +120,6 @@ s
[PATCH v8 1/7] arm64: cpufeature: Detect CPU RAS Extentions
From: Xie XiuQi ARM's v8.2 Extentions add support for Reliability, Availability and Serviceability (RAS). On CPUs with these extensions system software can use additional barriers to isolate errors and determine if faults are pending. Add cpufeature detection and a barrier in the context-switch code. There is no need to use alternatives for this as CPUs that don't support this feature will treat the instruction as a nop. Platform level RAS support may require additional firmware support. Signed-off-by: Xie XiuQi [Rebased, added esb and config option, reworded commit message] Signed-off-by: James Morse Signed-off-by: Dongjiu Geng Reviewed-by: Catalin Marinas --- arch/arm64/Kconfig | 16 arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kernel/cpufeature.c | 13 + arch/arm64/kernel/process.c | 3 +++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 0df64a6..cc00d10 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -973,6 +973,22 @@ config ARM64_PMEM operations if DC CVAP is not supported (following the behaviour of DC CVAP itself if the system does not define a point of persistence). +config ARM64_RAS_EXTN + bool "Enable support for RAS CPU Extensions" + default y + help + CPUs that support the Reliability, Availability and Serviceability + (RAS) Extensions, part of ARMv8.2 are able to track faults and + errors, classify them and report them to software. + + On CPUs with these extensions system software can use additional + barriers to determine if faults are pending and read the + classification from a new set of registers. + + Selecting this feature will allow the kernel to use these barriers + and access the new registers if the system supports the extension. + Platform RAS features may additionally depend on firmware support. + endmenu config ARM64_MODULE_CMODEL_LARGE diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 0fe7e43..8b0a0eb 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -30,6 +30,7 @@ #define isb() asm volatile("isb" : : : "memory") #define dmb(opt) asm volatile("dmb " #opt : : : "memory") #define dsb(opt) asm volatile("dsb " #opt : : : "memory") +#define esb() asm volatile("hint #16" : : : "memory") #define mb() dsb(sy) #define rmb() dsb(ld) diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 8da6216..4820d44 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -40,7 +40,8 @@ #define ARM64_WORKAROUND_85892119 #define ARM64_WORKAROUND_CAVIUM_30115 20 #define ARM64_HAS_DCPOP21 +#define ARM64_HAS_RAS_EXTN 22 -#define ARM64_NCAPS22 +#define ARM64_NCAPS23 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index f707fed..64e2a80 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -332,6 +332,7 @@ #define ID_AA64ISAR1_DPB_SHIFT 0 /* id_aa64pfr0 */ +#define ID_AA64PFR0_RAS_SHIFT 28 #define ID_AA64PFR0_GIC_SHIFT 24 #define ID_AA64PFR0_ASIMD_SHIFT20 #define ID_AA64PFR0_FP_SHIFT 16 @@ -340,6 +341,7 @@ #define ID_AA64PFR0_EL1_SHIFT 4 #define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_RAS_V1 0x1 #define ID_AA64PFR0_FP_NI 0xf #define ID_AA64PFR0_FP_SUPPORTED 0x0 #define ID_AA64PFR0_ASIMD_NI 0xf diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 21e2c95..4846974 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -125,6 +125,7 @@ static int __init register_cpu_hwcaps_dumper(void) }; static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_RAS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), @@ -900,6 +901,18 @@ static bool has_no_fpsimd(const struct arm64_cpu_capabilities *entry, int __unus .min_field_value = 1, }, #endif +#ifdef CONFIG_ARM64_RAS_EXTN +
[PATCH v8 2/7] KVM: arm64: Save ESR_EL2 on guest SError
From: James Morse When we exit a guest due to an SError the vcpu fault info isn't updated with the ESR. Today this is only done for traps. The v8.2 RAS Extensions define ISS values for SError. Update the vcpu's fault_info with the ESR on SError so that handle_exit() can determine if this was a RAS SError and decode its severity. Signed-off-by: James Morse Signed-off-by: Dongjiu Geng --- arch/arm64/kvm/hyp/switch.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 945e79c..c6f17c7 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -226,13 +226,20 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) return true; } +static void __hyp_text __populate_fault_info_esr(struct kvm_vcpu *vcpu) +{ + vcpu->arch.fault.esr_el2 = read_sysreg_el2(esr); +} + static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) { - u64 esr = read_sysreg_el2(esr); - u8 ec = ESR_ELx_EC(esr); + u8 ec; + u64 esr; u64 hpfar, far; - vcpu->arch.fault.esr_el2 = esr; + __populate_fault_info_esr(vcpu); + esr = vcpu->arch.fault.esr_el2; + ec = ESR_ELx_EC(esr); if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) return true; @@ -321,6 +328,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) */ if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu)) goto again; + else if (ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_EL1_SERROR) + __populate_fault_info_esr(vcpu); if (static_branch_unlikely(&vgic_v2_cpuif_trap) && exit_code == ARM_EXCEPTION_TRAP) { -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v1 0/3] manually add Error Synchronization Barrier at exception handler entry and exit
Some hardware platform can support RAS Extension, but not support IESB, such as Huawei's platform, so software need to insert Synchronization Barrier operations at exception handler entry. This series patches are based on James's series patches "SError rework + RAS&IESB for firmware first support". In Huawei's platform, we do not support IESB, so software needs to insert that. Dongjiu Geng (3): arm64: add a macro for SError synchronization arm64: add error synchronization barrier in kernel_entry/kernel_exit KVM: arm64: add ESB in exception handler entry and exit. James Morse (18): arm64: explicitly mask all exceptions arm64: introduce an order for exceptions arm64: Move the async/fiq helpers to explicitly set process context flags arm64: Mask all exceptions during kernel_exit arm64: entry.S: Remove disable_dbg arm64: entry.S: convert el1_sync arm64: entry.S convert el0_sync arm64: entry.S: convert elX_irq KVM: arm/arm64: mask/unmask daif around VHE guests arm64: kernel: Survive corrected RAS errors notified by SError arm64: cpufeature: Enable IESB on exception entry/return for firmware-first arm64: kernel: Prepare for a DISR user KVM: arm64: Set an impdef ESR for Virtual-SError using VSESR_EL2. KVM: arm64: Save/Restore guest DISR_EL1 KVM: arm64: Save ESR_EL2 on guest SError KVM: arm64: Handle RAS SErrors from EL1 on guest exit KVM: arm64: Handle RAS SErrors from EL2 on guest exit KVM: arm64: Take any host SError before entering the guest Xie XiuQi (2): arm64: entry.S: move SError handling into a C function for future expansion arm64: cpufeature: Detect CPU RAS Extentions arch/arm64/Kconfig | 33 +- arch/arm64/include/asm/assembler.h | 59 +--- arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 4 +- arch/arm64/include/asm/daifflags.h | 61 + arch/arm64/include/asm/esr.h | 17 +++ arch/arm64/include/asm/exception.h | 14 ++ arch/arm64/include/asm/irqflags.h| 40 ++-- arch/arm64/include/asm/kvm_emulate.h | 10 arch/arm64/include/asm/kvm_host.h| 16 +++ arch/arm64/include/asm/processor.h | 2 + arch/arm64/include/asm/sysreg.h | 6 +++ arch/arm64/include/asm/traps.h | 36 +++ arch/arm64/kernel/asm-offsets.c | 1 + arch/arm64/kernel/cpufeature.c | 43 ++ arch/arm64/kernel/debug-monitors.c | 5 +- arch/arm64/kernel/entry.S| 88 +--- arch/arm64/kernel/hibernate.c| 5 +- arch/arm64/kernel/machine_kexec.c| 4 +- arch/arm64/kernel/process.c | 3 ++ arch/arm64/kernel/setup.c| 8 ++-- arch/arm64/kernel/signal.c | 8 +++- arch/arm64/kernel/smp.c | 12 ++--- arch/arm64/kernel/suspend.c | 7 +-- arch/arm64/kernel/traps.c| 64 +- arch/arm64/kvm/handle_exit.c | 19 +++- arch/arm64/kvm/hyp-init.S| 3 ++ arch/arm64/kvm/hyp/entry.S | 15 ++ arch/arm64/kvm/hyp/hyp-entry.S | 1 + arch/arm64/kvm/hyp/switch.c | 19 ++-- arch/arm64/kvm/hyp/sysreg-sr.c | 6 +++ arch/arm64/kvm/inject_fault.c| 13 +- arch/arm64/kvm/sys_regs.c| 1 + arch/arm64/mm/proc.S | 14 -- virt/kvm/arm/arm.c | 4 ++ 35 files changed, 527 insertions(+), 115 deletions(-) create mode 100644 arch/arm64/include/asm/daifflags.h -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v1 1/3] arm64: add a macro for SError synchronization
ARMv8.2 adds a control bit to each SCTLR_ELx to insert implicit Error Synchronization Barrier(IESB) operations at exception handler entry and exit. But not all hardware platform which support RAS Extension can support IESB. So for this case, software needs to manually insert Error Synchronization Barrier(ESB) operations. In this macros, if system supports RAS Extensdddon instead of IESB, it will insert an ESB instruction. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/assembler.h | 9 + 1 file changed, 9 insertions(+) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index d4c0adf..e6c79c4 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -517,4 +517,13 @@ #endif .endm + .macro error_synchronize +alternative_if ARM64_HAS_IESB + b 1f +alternative_else_nop_endif +alternative_if ARM64_HAS_RAS_EXTN + esb +alternative_else_nop_endif +1: + .endm #endif /* __ASM_ASSEMBLER_H */ -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v1 3/3] KVM: arm64: add ESB in exception handler entry and exit.
Some hardware platform can support RAS Extension instead of support IESB, so software need to insert Synchronization Barrier operations at exception handler entry and exit. In the __guest_exit(), it added a ESB instruction, but can not cover the path which is not guest exit. For example, if EL1 host call HVC instruction enter to hypervisor, it will not call __guest_exit(). In the kvm_arm_vhe_guest_enter(), it synchronised any host RAS errors for VHE mode, but it can not handle the non-VHE mode. For example, if EL1 host is pending a SError, the error can be propagated to guest without error synchronization operation. Only add the ESB in the important exception handler path to reduce the impact on performance. Signed-off-by: Dongjiu Geng --- arch/arm64/kvm/hyp/entry.S | 2 ++ arch/arm64/kvm/hyp/hyp-entry.S | 1 + 2 files changed, 3 insertions(+) diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index 96caa53..fce6806 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S @@ -84,6 +84,8 @@ ENTRY(__guest_enter) // Restore guest reg x18 ldr x18, [x18, #CPU_XREG_OFFSET(18)] + // synchronize host pending asynchronous error + error_synchronize // Do not touch any register after this! eret ENDPROC(__guest_enter) diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 5170ce1..ac85029 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -54,6 +54,7 @@ ENTRY(__vhe_hyp_call) ENDPROC(__vhe_hyp_call) el1_sync: // Guest trapped into EL2 + error_synchronize stp x0, x1, [sp, #-16]! alternative_if_not ARM64_HAS_VIRT_HOST_EXTN -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v1 2/3] arm64: add error synchronization barrier in kernel_entry/kernel_exit
If taking an exception from or return to user space, insert a Error Synchronization Barrier(ESB) to isolate the error. If a user space process is pending a SError, when enter to kernel, the SError will be immediately synchronized in the handler entry. Otherwise if kernel space is pending a SError, before return to user space, the SError will be synchronized in the handler exit. In order to reduce impact on performance, not check the DISR_EL1 to see whether an SError is consumed by an ESB instruction. This is because DISR_EL1 is RAZ/WI in firmware-first RAS solution, if happen SError, it will immediately trap to EL3 firmware. Signed-off-by: Dongjiu Geng --- arch/arm64/kernel/entry.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index e147c1d..6dde644 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -138,6 +138,7 @@ stp x28, x29, [sp, #16 * 14] .if \el == 0 + error_synchronize mrs x21, sp_el0 ldr_this_cputsk, __entry_task, x20 // Ensure MDSCR_EL1.SS is clear, ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug @@ -281,6 +282,7 @@ alternative_if ARM64_WORKAROUND_845719 1: alternative_else_nop_endif #endif + error_synchronize .endif msr elr_el1, x21// set up the return data -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v4] KVM: arm/arm64: fix the incompatible matching for external abort
kvm_vcpu_dabt_isextabt() tries to match a full fault syndrome, but calls kvm_vcpu_trap_get_fault_type() that only returns the fault class, thus reducing the scope of the check. This doesn't cause any observable bug yet as we end-up matching a closely related syndrome for which we return the same value. Using kvm_vcpu_trap_get_fault() instead fixes it for good. Signed-off-by: Dongjiu Geng Acked-by: Marc Zyngier --- arch/arm/include/asm/kvm_emulate.h | 2 +- arch/arm64/include/asm/kvm_emulate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 98089ff..7571b4e 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h @@ -203,7 +203,7 @@ static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu) static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu) { - switch (kvm_vcpu_trap_get_fault_type(vcpu)) { + switch (kvm_vcpu_trap_get_fault(vcpu)) { case FSC_SEA: case FSC_SEA_TTW0: case FSC_SEA_TTW1: diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fc..8c918c5 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -237,7 +237,7 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) { - switch (kvm_vcpu_trap_get_fault_type(vcpu)) { + switch (kvm_vcpu_trap_get_fault(vcpu)) { case FSC_SEA: case FSC_SEA_TTW0: case FSC_SEA_TTW1: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v3] KVM: arm/arm64: fix the incompatible matching for external abort
For this matching, switch expression uses fault type which is not {I,D}FSC value, but the case expression uses {I,D}FSC, they are incompatible. So change the switch expression to use {I,D}FSC. Signed-off-by: Dongjiu Geng --- arch/arm/include/asm/kvm_emulate.h | 2 +- arch/arm64/include/asm/kvm_emulate.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 98089ff..7571b4e 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h @@ -203,7 +203,7 @@ static inline u8 kvm_vcpu_trap_get_fault_type(struct kvm_vcpu *vcpu) static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu) { - switch (kvm_vcpu_trap_get_fault_type(vcpu)) { + switch (kvm_vcpu_trap_get_fault(vcpu)) { case FSC_SEA: case FSC_SEA_TTW0: case FSC_SEA_TTW1: diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fc..8c918c5 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -237,7 +237,7 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) { - switch (kvm_vcpu_trap_get_fault_type(vcpu)) { + switch (kvm_vcpu_trap_get_fault(vcpu)) { case FSC_SEA: case FSC_SEA_TTW0: case FSC_SEA_TTW1: -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v2] KVM: arm/arm64: Fix external abort type matching
For this matching, current code using the {I,D}FSC range to match kvm_vcpu_trap_get_fault_type() return value, but kvm_vcpu_trap_get_fault_type() only return the part {I,D}FSC instead of whole, so fix this issue Value Type 0x10FSC_SEA 0x14FSC_SEA_TTW0 FSC_SEA_TTW1 FSC_SEA_TTW2 FSC_SEA_TTW3 0x18FSC_SECC 0x1cFSC_SECC_TTW0 FSC_SECC_TTW1 FSC_SECC_TTW2 FSC_SECC_TTW3 CC: James Morse CC: Tyler Baicar Signed-off-by: Dongjiu Geng --- As shown below code: The kvm_vcpu_trap_get_fault_type() only return {I,D}FSC bit[5]:bit[2], not the whole {I,D}FSC, but FSC_SEA_TTWx and FSC_SECC_TTWx are the whole {I,D}FSC value. static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu) { return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE; } static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) { switch (kvm_vcpu_trap_get_fault_type(vcpu)) { case FSC_SEA: case FSC_SEA_TTW0: case FSC_SEA_TTW1: case FSC_SEA_TTW2: case FSC_SEA_TTW3: case FSC_SECC: case FSC_SECC_TTW0: case FSC_SECC_TTW1: case FSC_SECC_TTW2: case FSC_SECC_TTW3: return true; default: return false; } } --- arch/arm/include/asm/kvm_arm.h | 10 ++ arch/arm/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_arm.h | 10 ++ arch/arm64/include/asm/kvm_emulate.h | 10 ++ 4 files changed, 8 insertions(+), 32 deletions(-) diff --git a/arch/arm/include/asm/kvm_arm.h b/arch/arm/include/asm/kvm_arm.h index c878145..b4b155c 100644 --- a/arch/arm/include/asm/kvm_arm.h +++ b/arch/arm/include/asm/kvm_arm.h @@ -188,15 +188,9 @@ #define FSC_ACCESS (0x08) #define FSC_PERM (0x0c) #define FSC_SEA(0x10) -#define FSC_SEA_TTW0 (0x14) -#define FSC_SEA_TTW1 (0x15) -#define FSC_SEA_TTW2 (0x16) -#define FSC_SEA_TTW3 (0x17) +#define FSC_SEA_TTW(0x14) #define FSC_SECC (0x18) -#define FSC_SECC_TTW0 (0x1c) -#define FSC_SECC_TTW1 (0x1d) -#define FSC_SECC_TTW2 (0x1e) -#define FSC_SECC_TTW3 (0x1f) +#define FSC_SECC_TTW (0x1c) /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ #define HPFAR_MASK (~0xf) diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h index 98089ff..aed8279 100644 --- a/arch/arm/include/asm/kvm_emulate.h +++ b/arch/arm/include/asm/kvm_emulate.h @@ -205,15 +205,9 @@ static inline bool kvm_vcpu_dabt_isextabt(struct kvm_vcpu *vcpu) { switch (kvm_vcpu_trap_get_fault_type(vcpu)) { case FSC_SEA: - case FSC_SEA_TTW0: - case FSC_SEA_TTW1: - case FSC_SEA_TTW2: - case FSC_SEA_TTW3: + case FSC_SEA_TTW: case FSC_SECC: - case FSC_SECC_TTW0: - case FSC_SECC_TTW1: - case FSC_SECC_TTW2: - case FSC_SECC_TTW3: + case FSC_SECC_TTW: return true; default: return false; diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..c0f1798 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -205,15 +205,9 @@ #define FSC_ACCESS ESR_ELx_FSC_ACCESS #define FSC_PERM ESR_ELx_FSC_PERM #define FSC_SEAESR_ELx_FSC_EXTABT -#define FSC_SEA_TTW0 (0x14) -#define FSC_SEA_TTW1 (0x15) -#define FSC_SEA_TTW2 (0x16) -#define FSC_SEA_TTW3 (0x17) +#define FSC_SEA_TTW(0x14) #define FSC_SECC (0x18) -#define FSC_SECC_TTW0 (0x1c) -#define FSC_SECC_TTW1 (0x1d) -#define FSC_SECC_TTW2 (0x1e) -#define FSC_SECC_TTW3 (0x1f) +#define FSC_SECC_TTW (0x1c) /* Hyp Prefetch Fault Address Register (HPFAR/HDFAR) */ #define HPFAR_MASK (~UL(0xf)) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index e5df3fc..5cde311 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -239,15 +239,9 @@ static inline bool kvm_vcpu_dabt_isextabt(const struct kvm_vcpu *vcpu) { switch (kvm_vcpu_trap_get_fault_type(vcpu)) { case FSC_SEA: - case FSC_SEA_TTW0: - case FSC_SEA_TTW1: - case FSC_SEA_TTW2: - case FSC_SEA_TTW3: + case FSC_SEA_TTW: case FSC_SECC: - case FSC_SECC_TTW0: - case FSC_SECC_TTW1: - case FSC_SECC_TTW2: - case FSC_SECC_TTW3: + case FSC_SECC_TTW: return true; default: return false; -- 1.9.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH RESEND v2] arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort
When a exception is trapped to EL2, hardware uses ELR_ELx to hold the current fault instruction address. If KVM wants to inject a abort to 32 bit guest, it needs to set the LR register for the guest to emulate this abort happened in the guest. Because ARM32 architecture is pipelined execution, so the LR value has an offset to the fault instruction address. The offsets applied to Link value for exceptions as shown below, which should be added for the ARM32 link register(LR). Table taken from ARMv8 ARM DDI0487B-B, table G1-10: Exception Offset, for PE state of: A32 T32 Undefined Instruction +4+2 Prefetch Abort +4+4 Data Abort +8+8 IRQ or FIQ +4+4 Signed-off-by: Dongjiu Geng Tested-by: Haibin Zhang --- Have tested in both arm32 and arm64 For example, in the arm64 platform, to the undefined instruction injection: 1. Guest OS call SMC(Secure Monitor Call) instruction in the address 0xc025405c, then Guest traps to hypervisor c0254050: e59d5028ldr r5, [sp, #40] ; 0x28 c0254054: e3a03001mov r3, #1 c0254058: e1a01003mov r1, r3 c025405c: e1600070smc 0 c0254060: e30a0270movwr0, #41584 ; 0xa270 c0254064: e34c00bfmovtr0, #49343 ; 0xc0bf 2. KVM injects undefined abort to guest 3. We will find the fault PC is 0xc0254058, not 0xc025405c. [ 12.348072] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM [ 12.349786] Modules linked in: [ 12.350563] CPU: 1 PID: 71 Comm: cat Not tainted 4.1.0-dirty #25 [ 12.352061] Hardware name: Generic DT based system [ 12.353275] task: d9d08000 ti: d9cfe000 task.ti: d9cfe000 [ 12.354637] PC is at proc_dointvec+0x20/0x60 [ 12.355717] LR is at proc_sys_call_handler+0xb0/0xc4 [ 12.356972] pc : []lr : []psr: a0060013 [ 12.356972] sp : d9cffe90 ip : c0254038 fp : 0001 [ 12.359824] r10: d9cfff80 r9 : 0004 r8 : [ 12.361132] r7 : bec21cb0 r6 : d9cffec4 r5 : d9cfff80 r4 : c0e82de0 [ 12.362766] r3 : 0001 r2 : bec21cb0 r1 : 0001 r0 : c0e82de0 [ 12.364400] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 12.366183] Control: 10c5383d Table: 59d3406a DAC: 0015 [ 12.367623] Process cat (pid: 71, stack limit = 0xd9cfe220) 4. After correct the LR register, it will have right value [ 125.763370] Internal error: Oops - undefined instruction: 0 [#2] SMP ARM [ 125.767010] Modules linked in: [ 125.768472] CPU: 1 PID: 74 Comm: cat Tainted: G D 4.1.0-dirty #25 [ 125.771854] Hardware name: Generic DT based system [ 125.774053] task: db0bb900 ti: d9d1 task.ti: d9d1 [ 125.776821] PC is at proc_dointvec+0x24/0x60 [ 125.778919] LR is at proc_sys_call_handler+0xb0/0xc4 [ 125.781269] pc : []lr : []psr: a0060013 [ 125.781269] sp : d9d11e90 ip : c0254038 fp : 0001 [ 125.786581] r10: d9d11f80 r9 : 0004 r8 : [ 125.789673] r7 : be92ccb0 r6 : d9d11ec4 r5 : d9d11f80 r4 : c0e82de0 [ 125.792828] r3 : 0001 r2 : be92ccb0 r1 : 0001 r0 : c0e82de0 [ 125.795890] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user For other exception injection, such as Data/Prefetch abort, also needs to correct --- arch/arm/kvm/emulate.c| 4 ++-- arch/arm64/kvm/inject_fault.c | 16 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 0064b86..2419328 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) u32 return_offset = (is_thumb) ? 2 : 4; kvm_update_psr(vcpu, UND_MODE); - *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset; + *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; /* Branch to exception vector */ *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; @@ -242,7 +242,7 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) unsigned long cpsr = *vcpu_cpsr(vcpu); bool is_thumb = (cpsr & PSR_T_BIT); u32 vect_offset; - u32 return_offset = (is_thumb) ? 4 : 0; + u32 return_offset = (is_pabt) ? 4 : 8; bool is_lpae; kvm_update_psr(vcpu, ABT_MODE); diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index da6a8cf..0416f18 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -33,12 +33,26 @@ #define LOWER_EL_AArch64_VECTOR0x400 #define LOWER_EL_AArch32_VECTOR0x600 +/* + * Table taken from ARMv8 ARM DDI0487B-B, table G1-10. + */ +static u8 return_offsets[8][2] = { + [0] = { 0, 0 }, /* Reset, unused */ + [1] = { 4, 2 }, /* Undefined */ + [2] = { 0, 0 }, /* SVC, unused */ + [3] = {
[PATCH v7 1/4] arm64: kvm: route synchronous external abort exceptions to EL2
ARMv8.2 adds a new bit HCR_EL2.TEA which controls to route synchronous external aborts to EL2, and adds a trap control bit HCR_EL2.TERR which controls to trap all Non-secure EL1&0 error record accesses to EL2. This patch enables the two bits for the guest OS. when an synchronous abort is generated in the guest OS, it will trap to EL3 firmware, EL3 firmware will check the HCR_EL2.TEA value to decide to jump to hypervisor or host OS. Enabling HCR_EL2.TERR makes error record access from guest trap to EL2. Add some minimal emulation for RAS-Error-Record registers. In the emulation, ERRIDR_EL1 and ERRSELR_EL1 are zero. Then, the others ERX* registers are RAZ/WI. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 10 + arch/arm64/kvm/sys_regs.c| 40 5 files changed, 61 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..1188272 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index fe39e68..47983db 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d686300..af55b3bc 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -105,6 +105,8 @@ enum vcpu_sysreg { TTBR1_EL1, /* Translation Table Base Register 1 */ TCR_EL1,/* Translation Control Register */ ESR_EL1,/* Exception Syndrome Register */ + ERRIDR_EL1, /* Error Record ID Register */ + ERRSELR_EL1,/* Error Record Select Register */ AFSR0_EL1, /* Auxiliary Fault Status Register 0 */ AFSR1_EL1, /* Auxiliary Fault Status Register 1 */ FAR_EL1,/* Fault Address Register */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 35b786b..bd11ca0 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -169,6 +169,16 @@ #define SYS_AFSR0_EL1 sys_reg(3, 0, 5, 1, 0) #define SYS_AFSR1_EL1 sys_reg(3, 0, 5, 1, 1) #define SYS_ESR_EL1sys_reg(3, 0, 5, 2, 0) + +#define SYS_ERRIDR_EL1 sys_reg(3, 0, 5, 3, 0) +#define SYS_ERRSELR_EL1sys_reg(3, 0, 5, 3, 1) +#define SYS_ERXFR_EL1 sys_reg(3, 0, 5, 4, 0) +#define SYS_ERXCTLR_EL1sys_reg(3, 0, 5, 4, 1) +#define SYS_ERXSTATUS_EL1 sys_reg(3, 0, 5, 4, 2) +#define SYS_ERXADDR_EL1sys_reg(3, 0, 5, 4, 3) +#define SYS_ERXMISC0_EL1 sys_reg(3, 0, 5, 5, 0) +#define SYS_ERXMISC1_EL1 sys_reg(3, 0, 5, 5, 1) + #define SYS_FAR_EL1sys_reg(3, 0, 6, 0, 0) #define SYS_PAR_EL1sys_reg(3, 0, 7, 4, 0) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2e070d3..a74617b 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -775,6 +775,36 @@ static bool access_pmovs(struct kvm_vcpu *vcpu, struct sys_reg_params *p, return true; } +static bool access_error_reg(struct kvm_vcpu *vcpu, struct sys_reg_params *p, +const struct sys_reg_desc *r) +{ + /* accessing ERRIDR_EL1 */ + if (r->CRm == 3 && r->Op2 == 0) { + if (p->is_write) + vcpu_sys_reg(vcpu, ERRIDR_EL1) = 0; + + return trap_raz_wi(vcpu, p, r); + } + + /* accessing ERRSELR_EL1 */ + if (r->CRm == 3 && r->Op2 == 1) { + if (p->is_write) + vcpu_sys_reg(vcpu, ERRSELR_EL1) = 0; + +
[PATCH v7 3/4] arm64: kvm: Set Virtual SError Exception Syndrome for guest
RAS Extension add a VSESR_EL2 register which can provides the syndrome value reported to software on taking a virtual SError interrupt exception. This patch supports to specify this Syndrome. In the RAS Extensions we can not set all-zero syndrome value for SError, which means 'RAS error: Uncategorized' instead of 'no valid ISS'. So set it to IMPLEMENTATION DEFINED syndrome by default. we also need to support userspace to specify a valid syndrome value, Because in some case, the recovery is driven by userspace. This patch can support that serspace can specify it. In the guest/host world switch, restore this value to VSESR_EL2 only when HCR_EL2.VSE is set. This value no need to be saved because it is stale vale when guest exit. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu [Set an impdef ESR for Virtual-SError] Signed-off-by: James Morse --- arch/arm64/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_host.h| 1 + arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/include/asm/system_misc.h | 1 - arch/arm64/kvm/guest.c | 11 ++- arch/arm64/kvm/hyp/switch.c | 15 +++ arch/arm64/kvm/inject_fault.c| 13 - 7 files changed, 51 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 47983db..74213bd 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault.vsesr_el2; +} + +static inline void kvm_vcpu_set_vsesr(struct kvm_vcpu *vcpu, unsigned long val) +{ + vcpu->arch.fault.vsesr_el2 = val; +} + static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index dd4cb25..1a0c07e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -88,6 +88,7 @@ struct kvm_vcpu_fault_info { u32 esr_el2;/* Hyp Syndrom Register */ u64 far_el2;/* Hyp Fault Address Register */ u64 hpfar_el2; /* Hyp IPA Fault Address Register */ + u32 vsesr_el2; /* Virtual SError Exception Syndrome Register */ }; /* diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index bd11ca0..e6c7fb8 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -86,6 +86,9 @@ #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) #define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3) +/* virtual SError exception syndrome register in armv8.2 */ +#define REG_VSESR_EL2 sys_reg(3, 4, 5, 2, 3) + #define SET_PSTATE_PAN(x) __emit_inst(0xd500 | REG_PSTATE_PAN_IMM | \ (!!x)<<8 | 0x1f) #define SET_PSTATE_UAO(x) __emit_inst(0xd500 | REG_PSTATE_UAO_IMM | \ diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3..e70cb61 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,7 +57,6 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); - #endif /* __ASSEMBLY__ */ #endif /* __ASM_SYSTEM_MISC_H */ diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 0a08b05..a9acbfd 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -279,7 +279,16 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u64 *syndrome) { - return -EINVAL; + u64 reg = *syndrome; + + /* inject virtual system Error or asynchronous abort */ + kvm_inject_vabt(vcpu); + + if (reg) + /* set vsesr_el2[24:0] with value that user space specified */ + kvm_vcpu_set_vsesr(vcpu, reg & ESR_ELx_ISS_MASK); + + return 0; } int __attribute_const__ kvm_target_cpu(void) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index c6f17c7..7c0915e 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -67,6 +67,14 @@ static hyp_alternate_select(__activate_traps_arch, __activate_traps_nvhe, __activate_traps_vhe, ARM64_HAS_VIRT_HOST_EXTN); +static void __hyp_text __sysreg_set_vsesr(struct kvm_vcpu *vcpu) +{ + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN) && + (vcpu->arch.hcr_el2 & HCR_VSE)) + write_sysreg_s(vcpu->arch.fault.vsesr_el2, REG_VSESR_EL2); +} + + stat
[PATCH v7 0/4] Add RAS virtualization support
In the firmware-first RAS solution, corrupt data is detected in a memory location when guest OS application software executing at EL0 or guest OS kernel El1 software are reading from the memory. The memory node records errors into an accessible system registers. Because SCR_EL3.EA is 1, then CPU will trap to El3 firmware, EL3 firmware records the error to APEI table through reading system register. Because the error was taken from a lower Exception level, if the exception is SEA/SEI and HCR_EL2.TEA/HCR_EL2.AMO is 1, firmware sets ESR_EL2/FAR_EL2 to fake a exception trap to EL2, then transfers to hypervisor. For the synchronous external abort(SEA), Hypervisor calls the handle_guest_sea() to deal with this error, which will reads the APEI table to get the error physical address, then call memory_failure() to identify the this address to poisoned and deliver SIGBUS signal to userspace. The advantage of using SIGBUS signal to notify user space is that it can be compatible with Non-Kvm users. For the SError Interrupt(SEI), KVM firstly classified the error. If the SError error comes from guest and is not propagated, then call handle_guest_sei() to let host firstly handle it. If the address recorded by APEI table is valid, then deliver SIGBUS signal to user space, user space will record the address to guest APEI table. Otherwise, directly injects virtual SError, or panic if the error is fatal. Sometime the error address recorded by APEI may be invalid(not accurate), and SIGBUS is not delivered to userspace. For this case, to make sure notify guest, userspace still inject virtual SError with specify syndrome to guest. The specify syndrome will be set to the VSESR_EL2. VSESR_EL2 is a new ARMv8.2 RAS extensions register which provides the syndrome value reported to software on taking a virtual SError interrupt exception. By default specify this syndrome value to IMPLEMENTATION DEFINED, because all-zero means 'RAS error: Uncategorized' instead of 'no valid ISS'. Dongjiu Geng (4): arm64: kvm: route synchronous external abort exceptions to EL2 arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl arm64: kvm: Set Virtual SError Exception Syndrome for guest arm64: kvm: handle SEI notification for guest Documentation/virtual/kvm/api.txt| 11 +++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 ++ arch/arm64/include/asm/esr.h | 10 ++ arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_asm.h | 1 + arch/arm64/include/asm/kvm_emulate.h | 17 ++ arch/arm64/include/asm/kvm_host.h| 11 +++ arch/arm64/include/asm/sysreg.h | 13 arch/arm64/include/asm/system_misc.h | 2 +- arch/arm64/kvm/guest.c | 14 + arch/arm64/kvm/handle_exit.c | 61 +--- arch/arm64/kvm/hyp/switch.c | 15 + arch/arm64/kvm/inject_fault.c| 13 +++- arch/arm64/kvm/reset.c | 3 ++ arch/arm64/kvm/sys_regs.c| 40 +++ arch/arm64/mm/fault.c| 16 ++ include/uapi/linux/kvm.h | 3 ++ virt/kvm/arm/arm.c | 7 + 19 files changed, 243 insertions(+), 6 deletions(-) -- 2.10.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v7 4/4] arm64: kvm: handle SEI notification for guest
when KVM received SError, it firstly classified the error according to [ESR_ELx.AET]. If the SEI is Uncategorized or IMPLEMENTATION DEFINED directly inject virtual SError with IMPLEMENTATION DEFINED syndrome. If the SError error is not propagated, then let host to handle it. Because usually the address recorded by APEI table is not accurate, so can not identify the address to hwpoison memory and can not notify guest to do the recovery, so at the same time, let user space specify a valid ESR and inject virtual SError. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/asm/esr.h | 15 + arch/arm64/include/asm/kvm_asm.h | 1 + arch/arm64/include/asm/kvm_host.h| 6 arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/handle_exit.c | 62 +--- arch/arm64/mm/fault.c| 16 ++ 6 files changed, 97 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 8cabd57..e5d23a8f 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -95,6 +95,7 @@ #define ESR_ELx_FSC_ACCESS (0x08) #define ESR_ELx_FSC_FAULT (0x04) #define ESR_ELx_FSC_PERM (0x0C) +#define ESR_ELx_FSC_SERROR (0x11) /* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV(UL(1) << 24) @@ -107,6 +108,20 @@ #define ESR_ELx_AR (UL(1) << 14) #define ESR_ELx_CM (UL(1) << 8) +/* ISS field definitions for SError interrupt */ +#define ESR_ELx_AET_SHIFT (10) +#define ESR_ELx_AET(UL(0x7) << ESR_ELx_AET_SHIFT) +/* Uncontainable error */ +#define ESR_ELx_AET_UC (UL(0) << ESR_ELx_AET_SHIFT) +/* Unrecoverable error */ +#define ESR_ELx_AET_UEU(UL(1) << ESR_ELx_AET_SHIFT) +/* Restartable error */ +#define ESR_ELx_AET_UEO(UL(2) << ESR_ELx_AET_SHIFT) +/* Recoverable error */ +#define ESR_ELx_AET_UER(UL(3) << ESR_ELx_AET_SHIFT) +/* Corrected */ +#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT) + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 26a64d0..d167ed3 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h @@ -27,6 +27,7 @@ #define ARM_EXCEPTION_IRQ0 #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 HVC_STUB_ERR diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 1a0c07e..c0da350 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -395,4 +395,10 @@ static inline void __cpu_init_stage2(void) "PARange is %d bits, unsupported configuration!", parange); } +enum { + KVM_SEI_SEV_RECOVERABLE = 1, + KVM_SEI_SEV_FATAL, + KVM_SEI_SEV_CORRECTED, +}; + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index e70cb61..73b45fb 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(unsigned int esr); #endif /* __ASSEMBLY__ */ #endif /* __ASM_SYSTEM_MISC_H */ diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 17d8a16..d546d55 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -178,6 +179,61 @@ static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu) return arm_exit_handlers[hsr_ec]; } +/** + * kvm_handle_guest_sei - handles SError interrupt or asynchronous aborts + * @vcpu: the VCPU pointer + * + * For RAS SError interrupt, if the AET is [ESR_ELx_AET_UEU] or + * [ESR_ELx_AET_UER], then let host user space do the recovery, + * otherwise, directly inject virtual SError to guest or panic. + */ +static int kvm_handle_guest_sei(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + unsigned int esr = kvm_vcpu_get_hsr(vcpu); + bool impdef_syndrome = esr & ESR_ELx_ISV; /* aka IDS */ + unsigned int aet = esr & ESR_ELx_AET; + + run->exit_reason = KVM_EXIT_EXCEPTION; + run->ex.exception = ARM_EXCEPTION_EL1_SERROR; + + /* +* In below three conditions, it will directly inject the +* virtual SError: +* 1. Not support RAS extens
[PATCH v7 2/4] arm64: kvm: Introduce KVM_ARM_SET_SERROR_ESR ioctl
On ARM64 SError syndrome value is specific to the model being emulated for the guest and user space needs a way to tell the kernel this value. userspace can specify different value to affect guest OS error recovery behaviour. We make this API ARM-specific as we haven't yet reached a consensus for a generic API for all KVM architectures that will allow us to do something like this. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- Documentation/virtual/kvm/api.txt | 11 +++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/guest.c | 9 + arch/arm64/include/asm/kvm_host.h | 2 ++ arch/arm64/kvm/guest.c| 5 + arch/arm64/kvm/reset.c| 3 +++ include/uapi/linux/kvm.h | 3 +++ virt/kvm/arm/arm.c| 7 +++ 8 files changed, 41 insertions(+) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index e63a35f..b076fc8 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -4347,3 +4347,14 @@ This capability indicates that userspace can load HV_X64_MSR_VP_INDEX msr. Its value is used to denote the target vcpu for a SynIC interrupt. For compatibilty, KVM initializes this msr to KVM's internal vcpu index. When this capability is absent, userspace can still query this msr's value. + +8.13 KVM_CAP_ARM_SET_SERROR_ESR + +Architectures: arm, arm64 + +This capability indicates that userspace can specify syndrome value reported to +software on taking a virtual SError interrupt exception. +Userspace can only specify the ISS field for the ESR syndrome, EC field is set +by hardware when the virtual SError interrupt is taken. If this virtual SError +is taken to EL1 using AArch64, this value will be reported in ESR_EL1, otherwise +if it is taken to EL1 using AArch32, this value will be reported in DFSR.{AET, ExT}. diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 127e2dd..3723138 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -211,6 +211,7 @@ unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu); int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u64 *syndrome); unsigned long kvm_call_hyp(void *hypfn, ...); void force_vm_exit(const cpumask_t *mask); diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784e..309b236 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,15 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +/* + * we only support SEI injection with specified synchronous + * in ARM64, not support it in ARM32. + */ +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u64 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index af55b3bc..dd4cb25 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -320,6 +320,8 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *indices); int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg); +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u64 *syndrome); + #define KVM_ARCH_WANT_MMU_NOTIFIER int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); int kvm_unmap_hva_range(struct kvm *kvm, diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 5c7f657..0a08b05 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -277,6 +277,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_arm_set_sei_esr(struct kvm_vcpu *vcpu, u64 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { unsigned long implementor = read_cpuid_implementor(); diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b92..9163628 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_SET_SERROR_ESR: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6cd63c1..aece611 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -929,6 +929,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_S
[PATCH v2] arm/arm64: KVM: set right LR register value for 32 bit guest when inject abort
When a exception is trapped to EL2, hardware uses ELR_ELx to hold the current fault instruction address. If KVM wants to inject a abort to 32 bit guest, it needs to set the LR register for the guest to emulate this abort happened in the guest. Because ARM32 architecture is pipelined execution, so the LR value has an offset to the fault instruction address. The offsets applied to Link value for exceptions as shown below, which should be added for the ARM32 link register(LR). Table taken from ARMv8 ARM DDI0487B-B, table G1-10: Exception Offset, for PE state of: A32 T32 Undefined Instruction +4+2 Prefetch Abort +4+4 Data Abort +8+8 IRQ or FIQ +4+4 Signed-off-by: Dongjiu Geng Tested-by: Haibin Zhang --- Note: now only test it in the arm64 host because there is no arm32 host environment, firstly send the patch out for review. In the arm64 platform, to the undefined instruction injection: 1. Guest OS call SMC(Secure Monitor Call) instruction in the address 0xc025405c, then Guest traps to hypervisor c0254050: e59d5028ldr r5, [sp, #40] ; 0x28 c0254054: e3a03001mov r3, #1 c0254058: e1a01003mov r1, r3 c025405c: e1600070smc 0 c0254060: e30a0270movwr0, #41584 ; 0xa270 c0254064: e34c00bfmovtr0, #49343 ; 0xc0bf 2. KVM injects undefined abort to guest 3. We will find the fault PC is 0xc0254058, not 0xc025405c. [ 12.348072] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM [ 12.349786] Modules linked in: [ 12.350563] CPU: 1 PID: 71 Comm: cat Not tainted 4.1.0-dirty #25 [ 12.352061] Hardware name: Generic DT based system [ 12.353275] task: d9d08000 ti: d9cfe000 task.ti: d9cfe000 [ 12.354637] PC is at proc_dointvec+0x20/0x60 [ 12.355717] LR is at proc_sys_call_handler+0xb0/0xc4 [ 12.356972] pc : []lr : []psr: a0060013 [ 12.356972] sp : d9cffe90 ip : c0254038 fp : 0001 [ 12.359824] r10: d9cfff80 r9 : 0004 r8 : [ 12.361132] r7 : bec21cb0 r6 : d9cffec4 r5 : d9cfff80 r4 : c0e82de0 [ 12.362766] r3 : 0001 r2 : bec21cb0 r1 : 0001 r0 : c0e82de0 [ 12.364400] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 12.366183] Control: 10c5383d Table: 59d3406a DAC: 0015 [ 12.367623] Process cat (pid: 71, stack limit = 0xd9cfe220) 4. After correct the LR register, it will have right value [ 125.763370] Internal error: Oops - undefined instruction: 0 [#2] SMP ARM [ 125.767010] Modules linked in: [ 125.768472] CPU: 1 PID: 74 Comm: cat Tainted: G D 4.1.0-dirty #25 [ 125.771854] Hardware name: Generic DT based system [ 125.774053] task: db0bb900 ti: d9d1 task.ti: d9d1 [ 125.776821] PC is at proc_dointvec+0x24/0x60 [ 125.778919] LR is at proc_sys_call_handler+0xb0/0xc4 [ 125.781269] pc : []lr : []psr: a0060013 [ 125.781269] sp : d9d11e90 ip : c0254038 fp : 0001 [ 125.786581] r10: d9d11f80 r9 : 0004 r8 : [ 125.789673] r7 : be92ccb0 r6 : d9d11ec4 r5 : d9d11f80 r4 : c0e82de0 [ 125.792828] r3 : 0001 r2 : be92ccb0 r1 : 0001 r0 : c0e82de0 [ 125.795890] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user For other exception injection, such as Data/Prefetch abort, also needs to correct --- arch/arm/kvm/emulate.c| 4 ++-- arch/arm64/kvm/inject_fault.c | 16 +++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/arch/arm/kvm/emulate.c b/arch/arm/kvm/emulate.c index 0064b86..2419328 100644 --- a/arch/arm/kvm/emulate.c +++ b/arch/arm/kvm/emulate.c @@ -227,7 +227,7 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu) u32 return_offset = (is_thumb) ? 2 : 4; kvm_update_psr(vcpu, UND_MODE); - *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) - return_offset; + *vcpu_reg(vcpu, 14) = *vcpu_pc(vcpu) + return_offset; /* Branch to exception vector */ *vcpu_pc(vcpu) = exc_vector_base(vcpu) + vect_offset; @@ -242,7 +242,7 @@ static void inject_abt(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) unsigned long cpsr = *vcpu_cpsr(vcpu); bool is_thumb = (cpsr & PSR_T_BIT); u32 vect_offset; - u32 return_offset = (is_thumb) ? 4 : 0; + u32 return_offset = (is_pabt) ? 4 : 8; bool is_lpae; kvm_update_psr(vcpu, ABT_MODE); diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index da6a8cf..0416f18 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -33,12 +33,26 @@ #define LOWER_EL_AArch64_VECTOR0x400 #define LOWER_EL_AArch32_VECTOR0x600 +/* + * Table taken from ARMv8 ARM DDI0487B-B, table G1-10. + */ +static u8 return_offsets[8][2] = { + [0] = { 0, 0 }, /* Reset, unused */ + [1] = { 4, 2 }, /* Undef
[PATCH] arm64: KVM: set right LR register value for 32 bit guest when inject abort
When a exception is trapped to EL2, hardware uses ELR_ELx to hold the current fault instruction address. If KVM wants to inject a abort to 32 bit guest, it needs to set the LR register for the guest to emulate this abort happened in the guest. Because ARM32 architecture is Multi-pipeline, so the LR value has an offset to the fault instruction address. The offsets applied to Link value for exceptions as shown below, which should be added for the ARM32 link register(LR). Exception Offset, for PE state of: A32 T32 Undefined Instruction +4+2 Prefetch Abort +4+4 Data Abort +8+8 IRQ or FIQ +4+4 Signed-off-by: Dongjiu Geng Signed-off-by: Haibin Zhang --- For example, to the undefined instruction injection: 1. Guest OS call SMC(Secure Monitor Call) instruction in the address 0xc025405c, then Guest traps to hypervisor c0254050: e59d5028ldr r5, [sp, #40] ; 0x28 c0254054: e3a03001mov r3, #1 c0254058: e1a01003mov r1, r3 c025405c: e1600070smc 0 c0254060: e30a0270movwr0, #41584 ; 0xa270 c0254064: e34c00bfmovtr0, #49343 ; 0xc0bf 2. KVM injects undefined abort to guest 3. We will find the fault PC is 0xc0254058, not 0xc025405c. [ 12.348072] Internal error: Oops - undefined instruction: 0 [#1] SMP ARM [ 12.349786] Modules linked in: [ 12.350563] CPU: 1 PID: 71 Comm: cat Not tainted 4.1.0-dirty #25 [ 12.352061] Hardware name: Generic DT based system [ 12.353275] task: d9d08000 ti: d9cfe000 task.ti: d9cfe000 [ 12.354637] PC is at proc_dointvec+0x20/0x60 [ 12.355717] LR is at proc_sys_call_handler+0xb0/0xc4 [ 12.356972] pc : []lr : []psr: a0060013 [ 12.356972] sp : d9cffe90 ip : c0254038 fp : 0001 [ 12.359824] r10: d9cfff80 r9 : 0004 r8 : [ 12.361132] r7 : bec21cb0 r6 : d9cffec4 r5 : d9cfff80 r4 : c0e82de0 [ 12.362766] r3 : 0001 r2 : bec21cb0 r1 : 0001 r0 : c0e82de0 [ 12.364400] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user [ 12.366183] Control: 10c5383d Table: 59d3406a DAC: 0015 [ 12.367623] Process cat (pid: 71, stack limit = 0xd9cfe220) 4. After correct the LR register, it will have right value [ 125.763370] Internal error: Oops - undefined instruction: 0 [#2] SMP ARM [ 125.767010] Modules linked in: [ 125.768472] CPU: 1 PID: 74 Comm: cat Tainted: G D 4.1.0-dirty #25 [ 125.771854] Hardware name: Generic DT based system [ 125.774053] task: db0bb900 ti: d9d1 task.ti: d9d1 [ 125.776821] PC is at proc_dointvec+0x24/0x60 [ 125.778919] LR is at proc_sys_call_handler+0xb0/0xc4 [ 125.781269] pc : []lr : []psr: a0060013 [ 125.781269] sp : d9d11e90 ip : c0254038 fp : 0001 [ 125.786581] r10: d9d11f80 r9 : 0004 r8 : [ 125.789673] r7 : be92ccb0 r6 : d9d11ec4 r5 : d9d11f80 r4 : c0e82de0 [ 125.792828] r3 : 0001 r2 : be92ccb0 r1 : 0001 r0 : c0e82de0 [ 125.795890] Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user For other exception injection, such as Data/Prefetch abort, also needs to correct --- arch/arm64/kvm/inject_fault.c | 18 -- 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/arch/arm64/kvm/inject_fault.c b/arch/arm64/kvm/inject_fault.c index da6a8cf..da93508 100644 --- a/arch/arm64/kvm/inject_fault.c +++ b/arch/arm64/kvm/inject_fault.c @@ -33,12 +33,11 @@ #define LOWER_EL_AArch64_VECTOR0x400 #define LOWER_EL_AArch32_VECTOR0x600 -static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) +static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset, + u32 return_offset) { unsigned long cpsr; unsigned long new_spsr_value = *vcpu_cpsr(vcpu); - bool is_thumb = (new_spsr_value & COMPAT_PSR_T_BIT); - u32 return_offset = (is_thumb) ? 4 : 0; u32 sctlr = vcpu_cp15(vcpu, c1_SCTLR); cpsr = mode | COMPAT_PSR_I_BIT; @@ -65,7 +64,11 @@ static void prepare_fault32(struct kvm_vcpu *vcpu, u32 mode, u32 vect_offset) static void inject_undef32(struct kvm_vcpu *vcpu) { - prepare_fault32(vcpu, COMPAT_PSR_MODE_UND, 4); + unsigned long spsr_value = *vcpu_cpsr(vcpu); + bool is_thumb = (spsr_value & COMPAT_PSR_T_BIT); + u32 return_offset = (is_thumb) ? 2 : 4; + + prepare_fault32(vcpu, COMPAT_PSR_MODE_UND, 4, return_offset); } /* @@ -75,21 +78,24 @@ static void inject_undef32(struct kvm_vcpu *vcpu) static void inject_abt32(struct kvm_vcpu *vcpu, bool is_pabt, unsigned long addr) { - u32 vect_offset; + u32 vect_offset, return_offset; u32 *far, *fsr; bool is_lpae; if (is_pabt) { vect_offset = 12; + return_offset = 4;
[PATCH] arm64: KVM: VHE: reset PSTATE.UAO when switch to host
In VHE mode, host kernel runs in the EL2 and can enable 'User Access Override' when fs==KERNEL_DS so that it can access kernel memory. However, PSTATE.UAO is set to 0 on an exception taken from EL1 to EL2. Thus when VHE is used and exception taken from a guest UAO will be disabled and host will use the incorrect PSTATE.UAO. So check and reset the PSTATE.UAO when switching to host. Move the reset PSTATE.PAN on entry to EL2 together with PSTATE.UAO reset. Signed-off-by: Dongjiu Geng Signed-off-by: Haibin Zhang Tested-by: Dongjiu Geng --- arch/arm64/kvm/hyp/entry.S | 2 -- arch/arm64/kvm/hyp/switch.c | 12 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/hyp/entry.S b/arch/arm64/kvm/hyp/entry.S index 12ee62d..7662ef5 100644 --- a/arch/arm64/kvm/hyp/entry.S +++ b/arch/arm64/kvm/hyp/entry.S @@ -96,8 +96,6 @@ ENTRY(__guest_exit) add x1, x1, #VCPU_CONTEXT - ALTERNATIVE(nop, SET_PSTATE_PAN(1), ARM64_HAS_PAN, CONFIG_ARM64_PAN) - // Store the guest regs x2 and x3 stp x2, x3, [x1, #CPU_XREG_OFFSET(2)] diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index a733461..715b3941 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -22,6 +22,7 @@ #include #include #include +#include static bool __hyp_text __fpsimd_enabled_nvhe(void) { @@ -399,6 +400,17 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) __sysreg_restore_host_state(host_ctxt); + if (has_vhe()) { + /* +* PSTATE was not saved over guest enter/exit, re-enable +* any detecte features that might not have been set +* correctly. +*/ + uao_thread_switch(current); + asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), + ARM64_HAS_PAN, CONFIG_ARM64_PAN)); + } + if (fp_enabled) { __fpsimd_save_state(&guest_ctxt->gp_regs.fp_regs); __fpsimd_restore_state(&host_ctxt->gp_regs.fp_regs); -- 1.8.3.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 7/7] arm64: kvm: handle SEI notification and pass the virtual syndrome
After received SError, KVM firstly classified the error. Not call memory_failure() to handle it. Because the address recorded by APEI is not accurated, so can not identify the address to hwpoison memory. If the SError error come from guest user mode and is not propagated, then signal user space to handle it, otherwise, directly injects virtual SError, or panic if the error is fatal. user space will specify syndrome for the injected virtual SError. This syndrome value is set to the VSESR_EL2, VSESR_EL2 is a new ARMv8.2 RAS extensions register which provides the syndrome value reported to software on taking a virtual SError interrupt exception. change since v5: 1. not call the memory_failure() to handle the SEI error 2. kvm classify the SError and decide how to do. 3. add code to deliver signal compatible to Non-KVM user. 4. correct some typo errors Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm/include/asm/kvm_host.h | 2 ++ arch/arm/kvm/guest.c | 9 ++ arch/arm64/include/asm/esr.h | 11 +++ arch/arm64/include/asm/kvm_emulate.h | 10 +++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 3 ++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/guest.c | 14 + arch/arm64/kvm/handle_exit.c | 56 arch/arm64/kvm/hyp/switch.c | 14 + arch/arm64/mm/fault.c| 34 ++ include/uapi/linux/kvm.h | 2 ++ virt/kvm/arm/arm.c | 7 + 13 files changed, 160 insertions(+), 5 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 127e2dd2e21c..bdb6ea690257 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -244,6 +244,8 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *); int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index); +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome); + static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, unsigned long hyp_stack_ptr, unsigned long vector_ptr) diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784ebbfd6..e120e7458c30 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,15 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +/* + * we only support SEI injection with specified synchronous + * in ARM64, not support it in ARM32. + */ +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome) +{ + return -EINVAL; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 8cabd57b6348..fe4a543add8f 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -77,6 +77,7 @@ #define ESR_ELx_EC_MASK(UL(0x3F) << ESR_ELx_EC_SHIFT) #define ESR_ELx_EC(esr)(((esr) & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT) + #define ESR_ELx_IL (UL(1) << 25) #define ESR_ELx_ISS_MASK (ESR_ELx_IL - 1) @@ -95,6 +96,7 @@ #define ESR_ELx_FSC_ACCESS (0x08) #define ESR_ELx_FSC_FAULT (0x04) #define ESR_ELx_FSC_PERM (0x0C) +#define ESR_ELx_FSC_SERROR (0x11) /* ISS field definitions for Data Aborts */ #define ESR_ELx_ISV(UL(1) << 24) @@ -107,6 +109,15 @@ #define ESR_ELx_AR (UL(1) << 14) #define ESR_ELx_CM (UL(1) << 8) +/* ISS field definitions for SError interrupt */ +#define ESR_ELx_AET_SHIFT (10) +#define ESR_ELx_AET(UL(0x7) << ESR_ELx_AET_SHIFT) +#define ESR_ELx_AET_UC (UL(0) << ESR_ELx_AET_SHIFT)/* Uncontainable */ +#define ESR_ELx_AET_UEU(UL(1) << ESR_ELx_AET_SHIFT)/* Uncorrected Unrecoverable */ +#define ESR_ELx_AET_UEO(UL(2) << ESR_ELx_AET_SHIFT)/* Uncorrected Restartable */ +#define ESR_ELx_AET_UER(UL(3) << ESR_ELx_AET_SHIFT)/* Uncorrected Recoverable */ +#define ESR_ELx_AET_CE (UL(6) << ESR_ELx_AET_SHIFT)/* Corrected */ + /* ISS field definitions for exceptions taken in to Hyp */ #define ESR_ELx_CV (UL(1) << 24) #define ESR_ELx_COND_SHIFT (20) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 47983db27de2..74213bd539dc 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vc
[PATCH v6 0/7] Add RAS virtualization support for SEA/SEI notification type in KVM
In the firmware-first RAS solution, corrupt data is detected in a memory location when guest OS application software executing at EL0 or guest OS kernel El1 software are reading from the memory. The memory node records errors in an error record accessible using system registers. Because SCR_EL3.EA is 1, then CPU will trap to El3 firmware, EL3 firmware records the error to APEI table through reading system register. Because the error was taken from a lower Exception level, if the exception is SEA/SEI and HCR_EL2.TEA/HCR_EL2.AMO is 1, firmware sets ESR_EL2/FAR_EL2 to fake a exception trap to EL2, then transfers to hypervisor. For the synchronous external abort(SEA), Hypervisor calls the ghes_handle_memory_failure() to deal with this error, ghes_handle_memory_failure() function reads the APEI table and callls memory_failure() to decide whether it needs to deliver SIGBUS signal to user space, the advantage of using SIGBUS signal to notify user space is that it can be compatible with Non-Kvm users. For the SError Interrupt(SEI),KVM firstly classified the error. Not call memory_failure() to handle it. Because the error address recorded by APEI is not accurated, so can not identify the address to hwpoison memory. If the SError error comes from guest user mode and is not propagated, then signal user space to handle it, otherwise, directly injects virtual SError, or panic if the error is fatal. when user space handles the error, it will specify syndrome for the injected virtual SError. This syndrome value is set to the VSESR_EL2. VSESR_EL2 is a new ARMv8.2 RAS extensions register which provides the syndrome value reported to software on taking a virtual SError interrupt exception. Dongjiu Geng (5): acpi: apei: remove the unused code arm64: kvm: support user space to query RAS extension feature arm64: kvm: route synchronous external abort exceptions to el2 KVM: arm64: allow get exception information from userspace arm64: kvm: handle SEI notification and pass the virtual syndrome James Morse (1): KVM: arm64: Save ESR_EL2 on guest SError Xie XiuQi (1): arm64: cpufeature: Detect CPU RAS Extentions arch/arm/include/asm/kvm_host.h | 2 ++ arch/arm/kvm/guest.c | 9 ++ arch/arm64/Kconfig | 16 +++ arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/esr.h | 11 +++ arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 17 +++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 5 arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/include/uapi/asm/kvm.h| 5 arch/arm64/kernel/cpufeature.c | 13 + arch/arm64/kernel/process.c | 3 ++ arch/arm64/kvm/guest.c | 50 arch/arm64/kvm/handle_exit.c | 56 arch/arm64/kvm/hyp/switch.c | 29 +-- arch/arm64/kvm/reset.c | 3 ++ arch/arm64/mm/fault.c| 34 ++ drivers/acpi/apei/ghes.c | 14 - include/uapi/linux/kvm.h | 3 ++ virt/kvm/arm/arm.c | 7 + 22 files changed, 263 insertions(+), 23 deletions(-) -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 2/7] KVM: arm64: Save ESR_EL2 on guest SError
From: James Morse When we exit a guest due to an SError the vcpu fault info isn't updated with the ESR. Today this is only done for traps. The v8.2 RAS Extensions define ISS values for SError. Update the vcpu's fault_info with the ESR on SError so that handle_exit() can determine if this was a RAS SError and decode its severity. Signed-off-by: James Morse --- arch/arm64/kvm/hyp/switch.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 945e79c641c4..c6f17c7675ad 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -226,13 +226,20 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) return true; } +static void __hyp_text __populate_fault_info_esr(struct kvm_vcpu *vcpu) +{ + vcpu->arch.fault.esr_el2 = read_sysreg_el2(esr); +} + static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) { - u64 esr = read_sysreg_el2(esr); - u8 ec = ESR_ELx_EC(esr); + u8 ec; + u64 esr; u64 hpfar, far; - vcpu->arch.fault.esr_el2 = esr; + __populate_fault_info_esr(vcpu); + esr = vcpu->arch.fault.esr_el2; + ec = ESR_ELx_EC(esr); if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) return true; @@ -321,6 +328,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) */ if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu)) goto again; + else if (ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_EL1_SERROR) + __populate_fault_info_esr(vcpu); if (static_branch_unlikely(&vgic_v2_cpuif_trap) && exit_code == ARM_EXCEPTION_TRAP) { -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 5/7] arm64: kvm: route synchronous external abort exceptions to el2
ARMv8.2 adds a new bit HCR_EL2.TEA which controls to route synchronous external aborts to EL2, and adds a trap control bit HCR_EL2.TERR which controls to trap all Non-secure EL1&0 error record accesses to EL2. This patch enables the two bits for the guest OS. when an synchronous abort is generated in the guest OS, it will trap to EL3 firmware, EL3 firmware will check the HCR_EL2.TEA value to decide to jump to hypervisor or host OS. Enabling HCR_EL2.TERR makes error record access from guest trap to EL2. change since v5: 1. modify some patch description Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ 2 files changed, 9 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c2eae5..1188272003c4 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index fe39e6841326..47983db27de2 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 4/7] arm64: kvm: support user space to query RAS extension feature
In ARMV8.2 RAS extension, a virtual SError exception syndrome register(VSESR_EL2) is added. This value may be specified from userspace. Userspace will want to check if the CPU has the RAS extension. If it has, it wil specify the virtual SError syndrome value, otherwise it will not be set. This patch adds support for querying the availability of this extension. change since v5: 1. modify some patch description Signed-off-by: Dongjiu Geng --- arch/arm64/kvm/reset.c | 3 +++ include/uapi/linux/kvm.h | 1 + 2 files changed, 4 insertions(+) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b9228e75..b7313ee028e9 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_RAS_EXTENSION: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6cd63c18708a..5a2a338cae57 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -929,6 +929,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SMT_POSSIBLE 147 #define KVM_CAP_HYPERV_SYNIC2 148 #define KVM_CAP_HYPERV_VP_INDEX 149 +#define KVM_CAP_ARM_RAS_EXTENSION 150 #ifdef KVM_CAP_IRQ_ROUTING -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 3/7] acpi: apei: remove the unused code
In current code logic, the two functions ghes_sea_add() and ghes_sea_remove() are only called when CONFIG_ACPI_APEI_SEA is defined. If not, it will return errors in the ghes_probe() and not contiue. Hence, remove the unnecessary handling when CONFIG_ACPI_APEI_SEI is not defined. change since v5: 1. remove the SEI notification type handling, because the SEI is asynchronous exception and the address is not accurate. so not call memory_failure() to handle it. Signed-off-by: Dongjiu Geng --- drivers/acpi/apei/ghes.c | 14 -- 1 file changed, 14 deletions(-) diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d661d452b238..c15a08db2c7c 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -813,7 +813,6 @@ static struct notifier_block ghes_notifier_hed = { .notifier_call = ghes_notify_hed, }; -#ifdef CONFIG_ACPI_APEI_SEA static LIST_HEAD(ghes_sea); /* @@ -848,19 +847,6 @@ static void ghes_sea_remove(struct ghes *ghes) mutex_unlock(&ghes_list_mutex); synchronize_rcu(); } -#else /* CONFIG_ACPI_APEI_SEA */ -static inline void ghes_sea_add(struct ghes *ghes) -{ - pr_err(GHES_PFX "ID: %d, trying to add SEA notification which is not supported\n", - ghes->generic->header.source_id); -} - -static inline void ghes_sea_remove(struct ghes *ghes) -{ - pr_err(GHES_PFX "ID: %d, trying to remove SEA notification which is not supported\n", - ghes->generic->header.source_id); -} -#endif /* CONFIG_ACPI_APEI_SEA */ #ifdef CONFIG_HAVE_ACPI_APEI_NMI /* -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 6/7] KVM: arm64: allow get exception information from userspace
when userspace gets SIGBUS signal, it does not know whether this is a synchronous external abort or SError, so needs to get the exception syndrome. This patch allows userspace can get this values. For syndrome, only give userspace syndrome EC and ISS. Now we move the synchronous external abort injection logic to userspace, when userspace injects the SEA exception to guest OS, it needs to specify the far_el1 value, so this patch gives the exception virtual address to userspace. change since v5: 1. modify some patch description Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/uapi/asm/kvm.h | 5 + arch/arm64/kvm/guest.c| 36 2 files changed, 41 insertions(+) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 9f3ca24bbcc6..514261f682b8 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -181,6 +181,11 @@ struct kvm_arch_memory_slot { #define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0007 #define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0 +/* AArch64 fault registers */ +#define KVM_REG_ARM64_FAULT(0x0014 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM64_FAULT_ESR_EC_ISS (0) +#define KVM_REG_ARM64_FAULT_FAR(1) + #define ARM64_SYS_REG_SHIFT_MASK(x,n) \ (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \ KVM_REG_ARM64_SYSREG_ ## n ## _MASK) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 5c7f657dd207..020a644b20d7 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -128,6 +128,39 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) out: return err; } +static int get_fault_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) +{ + void __user *uaddr = (void __user *)(unsigned long)reg->addr; + u32 value; + u32 id = reg->id & ~(KVM_REG_ARCH_MASK | + KVM_REG_SIZE_MASK | KVM_REG_ARM64_FAULT); + + switch (id) { + case KVM_REG_ARM64_FAULT_ESR_EC_ISS: + /* +* The user space may need to know the fault exception class +* ESR_ELx.EC and instruction specific syndrome ESR_ELx.ISS +*/ + value = kvm_vcpu_get_hsr(vcpu) & (ESR_ELx_EC_MASK | ESR_ELx_ISS_MASK); + if (copy_to_user(uaddr, &value, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; + break; + case KVM_REG_ARM64_FAULT_FAR: + /* +* When user space injects synchronized abort, it needs +* to inject the faulting virtual address to guest OS, so +* needs to get it from kvm. +*/ + if (copy_to_user(uaddr, &(vcpu->arch.fault.far_el2), + KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; + break; + default: + return -ENOENT; + } + return 0; +} + int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) { @@ -243,6 +276,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) return get_core_reg(vcpu, reg); + if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM64_FAULT) + return get_fault_reg(vcpu, reg); + if (is_timer_reg(reg->id)) return get_timer_reg(vcpu, reg); -- 2.14.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v6 1/7] arm64: cpufeature: Detect CPU RAS Extentions
From: Xie XiuQi ARM's v8.2 Extentions add support for Reliability, Availability and Serviceability (RAS). On CPUs with these extensions system software can use additional barriers to isolate errors and determine if faults are pending. Add cpufeature detection and a barrier in the context-switch code. There is no need to use alternatives for this as CPUs that don't support this feature will treat the instruction as a nop. Platform level RAS support may require additional firmware support. Signed-off-by: Xie XiuQi [Rebased, added esb and config option, reworded commit message] Signed-off-by: James Morse --- arch/arm64/Kconfig | 16 arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kernel/cpufeature.c | 13 + arch/arm64/kernel/process.c | 3 +++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index dfd908630631..4d87aa963d83 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -960,6 +960,22 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature. +config ARM64_RAS_EXTN + bool "Enable support for RAS CPU Extensions" + default y + help + CPUs that support the Reliability, Availability and Serviceability + (RAS) Extensions, part of ARMv8.2 are able to track faults and + errors, classify them and report them to software. + + On CPUs with these extensions system software can use additional + barriers to determine if faults are pending and read the + classification from a new set of registers. + + Selecting this feature will allow the kernel to use these barriers + and access the new registers if the system supports the extension. + Platform RAS features may additionally depend on firmware support. + endmenu config ARM64_MODULE_CMODEL_LARGE diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 0fe7e43b7fbc..8b0a0eb67625 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -30,6 +30,7 @@ #define isb() asm volatile("isb" : : : "memory") #define dmb(opt) asm volatile("dmb " #opt : : : "memory") #define dsb(opt) asm volatile("dsb " #opt : : : "memory") +#define esb() asm volatile("hint #16" : : : "memory") #define mb() dsb(sy) #define rmb() dsb(ld) diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 8d2272c6822c..f93bf77f1f74 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -39,7 +39,8 @@ #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 #define ARM64_WORKAROUND_85892119 #define ARM64_WORKAROUND_CAVIUM_30115 20 +#define ARM64_HAS_RAS_EXTN 21 -#define ARM64_NCAPS21 +#define ARM64_NCAPS22 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 248339e4aaf5..35b786b43ee4 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -331,6 +331,7 @@ #define ID_AA64ISAR1_JSCVT_SHIFT 12 /* id_aa64pfr0 */ +#define ID_AA64PFR0_RAS_SHIFT 28 #define ID_AA64PFR0_GIC_SHIFT 24 #define ID_AA64PFR0_ASIMD_SHIFT20 #define ID_AA64PFR0_FP_SHIFT 16 @@ -339,6 +340,7 @@ #define ID_AA64PFR0_EL1_SHIFT 4 #define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_RAS_V1 0x1 #define ID_AA64PFR0_FP_NI 0xf #define ID_AA64PFR0_FP_SUPPORTED 0x0 #define ID_AA64PFR0_ASIMD_NI 0xf diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9f9e0064c8c1..a807ab55ee10 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -124,6 +124,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { }; static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_RAS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), @@ -888,6 +889,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .min_field_value = 0, .matches = has_no_fpsimd, }, +#ifdef CONFIG_ARM64_RAS_EXTN + { + .desc = "RAS Extension Support", + .capability = ARM64_HAS_RAS_EXTN, + .def_scope = SCOPE_SYSTEM, + .matches = has_cp
[PATCH v11 2/6] ACPI: Add APEI GHES Table Generation support
This implements APEI GHES Table by passing the error CPER info to the guest via a fw_cfg_blob. After a CPER info is recorded, an SEA(Synchronous External Abort)/SEI(SError Interrupt) exception will be injected into the guest OS. Below is the table layout, the max number of error soure is 11, which is classified by notification type. etc/acpi/tables etc/hardware_errors == + +--++--+ | | HEST ||address | +--+ | +--+|registers | | Error Status | | | GHES0|| ++ | Data Block 0 | | +--+ +->| |status_address0 |->| ++ | | .| | | ++ | | CPER | | | error_status_address-+-+ +--->| |status_address1 |--+ | | CPER | | | .| || ++ | | | | | | read_ack_register+-+ || . | | | | CPER | | | read_ack_preserve| | |+--+ | | +-++ | | read_ack_write | | | +->| |status_address10|+ | | Error Status | + +--+ | | | | ++| | | Data Block 1 | | | GHES1| +-+-+->| | ack_value0 || +-->| ++ + +--+ | | | ++| | | CPER | | | .| | | +--->| | ack_value1 || | | CPER | | | error_status_address-+---+ | || ++| | | | | | .| | || | . || | | CPER | | | read_ack_register+-+-+| ++| +-++ | | read_ack_preserve| | +->| | ack_value10|| | |.. | | | read_ack_write | | | | ++| | ++ + +--| | | | | Error Status | | | ... | | | | | Data Block 10| + +--+ | | +>| ++ | | GHES10 | | || | CPER | + +--+ | || | CPER | | | .| | || | | | | error_status_address-+-+ || | CPER | | | .| | +-++ | | read_ack_register+-+ | | read_ack_preserve| | | read_ack_write | + +--+ For GHESv2 error source, the OSPM must acknowledges the error via Read Ack register. so user space must check the ack value to avoid read-write race condition. Signed-off-by: Dongjiu Geng --- hw/acpi/aml-build.c | 2 + hw/acpi/hest_ghes.c | 345 hw/arm/virt-acpi-build.c| 6 + include/hw/acpi/aml-build.h | 1 + include/hw/acpi/hest_ghes.h | 47 ++ 5 files changed, 401 insertions(+) create mode 100644 hw/acpi/hest_ghes.c create mode 100644 include/hw/acpi/hest_ghes.h diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 36a6cc4..6849e5f 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1561,6 +1561,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables) tables->table_data = g_array_new(false, true /* clear */, 1); tables->tcpalog = g_array_new(false, true /* clear */, 1); tables->vmgenid = g_array_new(false, true /* clear */, 1); +tables->hardware_errors = g_array_new(false, true /* clear */, 1); tables->linker = bios_linker_loader_init(); } @@ -1571,6 +1572,7 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre) g_array_free(tables->table_data, true); g_array_free(tables->tcpalog, mfre); g_array_free(tables->vmgenid, mfre); +g_array_free(tables->hardware_errors, mfre); } /* Build rsdt table */ diff --git a/hw/acpi/hest_ghes.c b/hw/acpi/hest_ghes.c new file mode 100644 index 000..ff6b5ef --- /dev/null +++ b/hw/acpi/hest_ghes.c @@ -0,0 +1,345 @@ +/* + * APEI GHES table Generation + * + * Copyright (C) 2017 huawei. + * + * Author: Dongjiu Geng + * + * This work is licensed under the terms of the GNU GPL, v
[PATCH v11 5/6] target-arm: kvm64: handle SIGBUS signal for synchronous External Abort
Add SIGBUS signal handler. In this handler, it checks the exception type, translates the host VA which is delivered by host or KVM to guest PA, then fills this PA to CPER, finally injects a Error to guest OS through KVM. Add synchronous external abort injection logic, setup spsr_elx, esr_elx, PSTATE, far_elx, elr_elx etc, when switch to guest OS, it will jump to the synchronous external abort vector table entry. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- include/sysemu/kvm.h | 2 +- linux-headers/asm-arm64/kvm.h | 5 ++ target/arm/internals.h| 13 target/arm/kvm.c | 34 ++ target/arm/kvm64.c| 150 ++ target/arm/kvm_arm.h | 1 + 6 files changed, 204 insertions(+), 1 deletion(-) diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 3a458f5..90c1605 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -361,7 +361,7 @@ bool kvm_vcpu_id_is_valid(int vcpu_id); /* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */ unsigned long kvm_arch_vcpu_id(CPUState *cpu); -#ifdef TARGET_I386 +#if defined(TARGET_I386) || defined(TARGET_AARCH64) #define KVM_HAVE_MCE_INJECTION 1 void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr); #endif diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index d254700..5909c30 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -181,6 +181,11 @@ struct kvm_arch_memory_slot { #define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0007 #define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0 +/* AArch64 fault registers */ +#define KVM_REG_ARM64_FAULT (0x0014 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM64_FAULT_ESR_EC (0) +#define KVM_REG_ARM64_FAULT_FAR (1) + #define ARM64_SYS_REG_SHIFT_MASK(x,n) \ (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \ KVM_REG_ARM64_SYSREG_ ## n ## _MASK) diff --git a/target/arm/internals.h b/target/arm/internals.h index 1f6efef..fc0ad6d 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -235,6 +235,19 @@ enum arm_exception_class { #define ARM_EL_ISV_SHIFT 24 #define ARM_EL_IL (1 << ARM_EL_IL_SHIFT) #define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT) +#define ARM_EL_EC_MASK ((0x3F) << ARM_EL_EC_SHIFT) +#define ARM_EL_FSC_TYPE (0x3C) + +#define FSC_SEA (0x10) +#define FSC_SEA_TTW0(0x14) +#define FSC_SEA_TTW1(0x15) +#define FSC_SEA_TTW2(0x16) +#define FSC_SEA_TTW3(0x17) +#define FSC_SECC(0x18) +#define FSC_SECC_TTW0 (0x1c) +#define FSC_SECC_TTW1 (0x1d) +#define FSC_SECC_TTW2 (0x1e) +#define FSC_SECC_TTW3 (0x1f) /* Utility functions for constructing various kinds of syndrome value. * Note that in general we follow the AArch64 syndrome values; in a diff --git a/target/arm/kvm.c b/target/arm/kvm.c index 7c17f0d..2e1716a 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -129,6 +129,39 @@ void kvm_arm_destroy_scratch_host_vcpu(int *fdarray) } } +typedef struct HWPoisonPage { +ram_addr_t ram_addr; +QLIST_ENTRY(HWPoisonPage) list; +} HWPoisonPage; + +static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list = +QLIST_HEAD_INITIALIZER(hwpoison_page_list); + +static void kvm_unpoison_all(void *param) +{ +HWPoisonPage *page, *next_page; + +QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) { +QLIST_REMOVE(page, list); +qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE); +g_free(page); +} +} + +void kvm_hwpoison_page_add(ram_addr_t ram_addr) +{ +HWPoisonPage *page; + +QLIST_FOREACH(page, &hwpoison_page_list, list) { +if (page->ram_addr == ram_addr) { +return; +} +} +page = g_new(HWPoisonPage, 1); +page->ram_addr = ram_addr; +QLIST_INSERT_HEAD(&hwpoison_page_list, page, list); +} + static void kvm_arm_host_cpu_class_init(ObjectClass *oc, void *data) { ARMHostCPUClass *ahcc = ARM_HOST_CPU_CLASS(oc); @@ -182,6 +215,7 @@ int kvm_arch_init(MachineState *ms, KVMState *s) cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE); +qemu_register_reset(kvm_unpoison_all, NULL); type_register_static(&host_arm_cpu_type_info); return 0; diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 0781367..d3bdab2 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -27,6 +27,8 @@ #include "kvm_arm.h" #include "internals.h" #include "hw/arm/arm.h" +#include "hw/acpi/acpi-defs.h" +#include "hw/acpi/hest_ghes.h" static bool have_guest_debug; @@ -590,6 +592,79 @@ int kvm_arm_cpreg_level(uint64_t regidx) return KVM_PUT_RUNTIME_STATE; } +static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset) +{ +int i; + +for (i = 0; i < cpu->cpreg_array_len; i++) { +uint32_t reg
[PATCH v11 0/6] Add RAS virtualization support for armv8 SEA and SEI
ss : 785D0048 [384h 0900 28] Notify : [Hardware Error Notification Structure] [384h 0900 1] Notify Type : 09 [SEI] [385h 0901 1]Notify Length : 1C [386h 0902 2] Configuration Write Enable : [388h 0904 4] PollInterval : [38Ch 0908 4] Vector : [390h 0912 4] Polling Threshold Value : [394h 0916 4] Polling Threshold Window : [398h 0920 4]Error Threshold Value : [39Ch 0924 4] Error Threshold Window : [3A0h 0928 4]Error Status Block Length : 1000 [3A4h 0932 12]Read Ack Register : [Generic Address Structure] [3A4h 0932 1] Space ID : 00 [SystemMemory] [3A5h 0933 1]Bit Width : 40 [3A6h 0934 1] Bit Offset : 00 [3A7h 0935 1] Encoded Access Width : 04 [QWord Access:64] [3A8h 0936 8] Address : 785D00A0 [3B0h 0944 8]Read Ack Preserve : FFFE [3B8h 0952 8] Read Ack Write : 0001 . (3) according to above table, the address that contains the physical address of a block of memory that holds the error status data for SEA notification error source is 0x785D0040 (4) the address for SEA notification error source is 0x785d8108 (qemu) xp /1 0x785D0040 785d0040: 0x785d80b0 (5) check the content of generic error status block and generic error data entry (qemu) xp /100x 0x785d80b0 785d80b0: 0x0001 0x 0x 0x0098 785d80c0: 0x 0xa5bc1114 0x4ede6f64 0x833e63b8 785d80d0: 0xb1837ced 0x 0x0300 0x0050 785d80e0: 0x 0x 0x 0x 785d80f0: 0x 0x 0x 0x 785d8100: 0x 0x 0x 0x4002 785d8110: 0x 0x 0x 0x 785d8120: 0x 0x 0x 0x 785d8130: 0x 0x 0x 0x 785d8140: 0x 0x 0x 0x 785d8150: 0x 0x0003 0x 0x 785d8160: 0x 0x 0x 0x 785d8170: 0x 0x 0x 0x 785d8180: 0x 0x 0x 0x 785d8190: 0x 0x 0x 0x 785d81a0: 0x 0x 0x 0x 785d81b0: 0x 0x 0x 0x 785d81c0: 0x 0x 0x 0x 785d81d0: 0x 0x 0x 0x 785d81e0: 0x 0x 0x 0x 785d81f0: 0x 0x 0x 0x 785d8200: 0x 0x 0x 0x 785d8210: 0x 0x 0x 0x 785d8220: 0x 0x 0x 0x 785d8230: 0x 0x 0x 0x (6) check the OSPM's ACK value(for example SEA) /* Before OSPM acknowledges the error, check the ACK value */ (qemu) xp /1 0x785D0098 785d00f0: 0x /* After OSPM acknowledges the error, check the ACK value */ (qemu) xp /1 0x785D0098 785d00f0: 0x0001 Dongjiu Geng (6): ACPI: add APEI/HEST/CPER structures and macros ACPI: Add APEI GHES Table Generation support ACPI: build and enable APEI GHES in the Makefile and configuration target-arm: kvm64: detect guest RAS EXTENSION feature target-arm: kvm64: handle SIGBUS signal for synchronous External Abort target-arm: kvm64: Handle SError interrupt from the guest OS default-configs/arm-softmmu.mak | 1 + hw/acpi/Makefile.objs | 1 + hw/acpi/aml-build.c | 2 + hw/acpi/hest_ghes.c | 345 hw/arm/virt-acpi-build.c| 6 + include/hw/acpi/acpi-defs.h | 193 ++ include/hw/acpi/aml-build.h | 1 + include/hw/acpi/hest_ghes.h | 47 ++ include/sysemu/kvm.h| 2 +- linux-headers/asm-arm64/kvm.h | 5 + linux-headers/linux/kvm.h | 2 + target/arm/cpu.h| 3 + target/arm/internals.h | 14 ++ target/arm/kvm.c| 34 target/arm/kvm64.c | 186 ++ target/arm/kvm_arm.h| 1 + 16 files changed, 842 insertions(+), 1 deletion(-) create mode 100644 hw/acpi/hest_ghes.c create mode 10064
[PATCH v11 3/6] ACPI: build and enable APEI GHES in the Makefile and configuration
Add CONFIG_ACPI_APEI configuration in the Makefile and enable it in the arm-softmmu.mak Signed-off-by: Dongjiu Geng --- default-configs/arm-softmmu.mak | 1 + hw/acpi/Makefile.objs | 1 + 2 files changed, 2 insertions(+) diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index bbdd3c1..c362113 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -129,3 +129,4 @@ CONFIG_ACPI=y CONFIG_SMBIOS=y CONFIG_ASPEED_SOC=y CONFIG_GPIO_KEY=y +CONFIG_ACPI_APEI=y diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs index 11c35bc..bafb148 100644 --- a/hw/acpi/Makefile.objs +++ b/hw/acpi/Makefile.objs @@ -6,6 +6,7 @@ common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu.o common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o +common-obj-$(CONFIG_ACPI_APEI) += hest_ghes.o common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o common-obj-y += acpi_interface.o -- 1.8.3.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v11 4/6] target-arm: kvm64: detect guest RAS EXTENSION feature
check if kvm supports guest RAS EXTENSION. if so, set corresponding feature bit for vcpu. Signed-off-by: Dongjiu Geng --- linux-headers/linux/kvm.h | 1 + target/arm/cpu.h | 3 +++ target/arm/kvm64.c| 8 3 files changed, 12 insertions(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 7971a4f..2aa176e 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -929,6 +929,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SMT_POSSIBLE 147 #define KVM_CAP_HYPERV_SYNIC2 148 #define KVM_CAP_HYPERV_VP_INDEX 149 +#define KVM_CAP_ARM_RAS_EXTENSION 150 #ifdef KVM_CAP_IRQ_ROUTING diff --git a/target/arm/cpu.h b/target/arm/cpu.h index b39d64a..6b0961b 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -611,6 +611,8 @@ struct ARMCPU { /* CPU has memory protection unit */ bool has_mpu; +/* CPU has ras extension unit */ +bool has_ras_extension; /* PMSAv7 MPU number of supported regions */ uint32_t pmsav7_dregion; @@ -1229,6 +1231,7 @@ enum arm_features { ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */ ARM_FEATURE_PMU, /* has PMU support */ ARM_FEATURE_VBAR, /* has cp15 VBAR */ +ARM_FEATURE_RAS_EXTENSION, /*has RAS extension support */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index a16abc8..0781367 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -518,6 +518,14 @@ int kvm_arch_init_vcpu(CPUState *cs) unset_feature(&env->features, ARM_FEATURE_PMU); } +if (kvm_check_extension(cs->kvm_state, KVM_CAP_ARM_RAS_EXTENSION)) { +cpu->has_ras_extension = true; +set_feature(&env->features, ARM_FEATURE_RAS_EXTENSION); +} else { +cpu->has_ras_extension = false; +unset_feature(&env->features, ARM_FEATURE_RAS_EXTENSION); +} + /* Do KVM_ARM_VCPU_INIT ioctl */ ret = kvm_arm_vcpu_init(cs); if (ret) { -- 1.8.3.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v11 1/6] ACPI: add APEI/HEST/CPER structures and macros
(1) Add related APEI/HEST table structures and macros, these definition refer to ACPI 6.1 and UEFI 2.6 spec. (2) Add generic error status block and CPER memory section definition, user space only handle memory section errors. Signed-off-by: Dongjiu Geng --- include/hw/acpi/acpi-defs.h | 193 1 file changed, 193 insertions(+) diff --git a/include/hw/acpi/acpi-defs.h b/include/hw/acpi/acpi-defs.h index 72be675..3b4bad7 100644 --- a/include/hw/acpi/acpi-defs.h +++ b/include/hw/acpi/acpi-defs.h @@ -297,6 +297,44 @@ typedef struct AcpiMultipleApicTable AcpiMultipleApicTable; #define ACPI_APIC_GENERIC_TRANSLATOR15 #define ACPI_APIC_RESERVED 16 /* 16 and greater are reserved */ +/* UEFI Spec 2.6, "N.2.5 Memory Error Section */ +#define UEFI_CPER_MEM_VALID_ERROR_STATUS 0x0001 +#define UEFI_CPER_MEM_VALID_PA 0x0002 +#define UEFI_CPER_MEM_VALID_PA_MASK 0x0004 +#define UEFI_CPER_MEM_VALID_NODE 0x0008 +#define UEFI_CPER_MEM_VALID_CARD 0x0010 +#define UEFI_CPER_MEM_VALID_MODULE 0x0020 +#define UEFI_CPER_MEM_VALID_BANK 0x0040 +#define UEFI_CPER_MEM_VALID_DEVICE 0x0080 +#define UEFI_CPER_MEM_VALID_ROW 0x0100 +#define UEFI_CPER_MEM_VALID_COLUMN 0x0200 +#define UEFI_CPER_MEM_VALID_BIT_POSITION 0x0400 +#define UEFI_CPER_MEM_VALID_REQUESTOR0x0800 +#define UEFI_CPER_MEM_VALID_RESPONDER0x1000 +#define UEFI_CPER_MEM_VALID_TARGET 0x2000 +#define UEFI_CPER_MEM_VALID_ERROR_TYPE 0x4000 +#define UEFI_CPER_MEM_VALID_RANK_NUMBER 0x8000 +#define UEFI_CPER_MEM_VALID_CARD_HANDLE 0x1 +#define UEFI_CPER_MEM_VALID_MODULE_HANDLE0x2 +#define UEFI_CPER_MEM_ERROR_TYPE_MULTI_ECC 3 + +/* From the ACPI 6.1 spec, "18.3.2.9 Hardware Error Notification" */ + +enum AcpiHestNotifyType { +ACPI_HEST_NOTIFY_POLLED = 0, +ACPI_HEST_NOTIFY_EXTERNAL = 1, +ACPI_HEST_NOTIFY_LOCAL = 2, +ACPI_HEST_NOTIFY_SCI = 3, +ACPI_HEST_NOTIFY_NMI = 4, +ACPI_HEST_NOTIFY_CMCI = 5, /* ACPI 5.0 */ +ACPI_HEST_NOTIFY_MCE = 6, /* ACPI 5.0 */ +ACPI_HEST_NOTIFY_GPIO = 7, /* ACPI 6.0 */ +ACPI_HEST_NOTIFY_SEA = 8, /* ACPI 6.1 */ +ACPI_HEST_NOTIFY_SEI = 9, /* ACPI 6.1 */ +ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */ +ACPI_HEST_NOTIFY_RESERVED = 11 /* 11 and greater are reserved */ +}; + /* * MADT sub-structures (Follow MULTIPLE_APIC_DESCRIPTION_TABLE) */ @@ -474,6 +512,161 @@ struct AcpiSystemResourceAffinityTable { } QEMU_PACKED; typedef struct AcpiSystemResourceAffinityTable AcpiSystemResourceAffinityTable; +/* Hardware Error Notification, from the ACPI 6.1 + * spec, "18.3.2.9 Hardware Error Notification" + */ +struct AcpiHestNotify { +uint8_t type; +uint8_t length; +uint16_t config_write_enable; +uint32_t poll_interval; +uint32_t vector; +uint32_t polling_threshold_value; +uint32_t polling_threshold_window; +uint32_t error_threshold_value; +uint32_t error_threshold_window; +} QEMU_PACKED; +typedef struct AcpiHestNotify AcpiHestNotify; + +/* From ACPI 6.1, sections "18.3.2.1 IA-32 Architecture Machine + * Check Exception" through "18.3.2.8 Generic Hardware Error Source version 2". + */ +enum AcpiHestSourceType { +ACPI_HEST_SOURCE_IA32_CHECK = 0, +ACPI_HEST_SOURCE_IA32_CORRECTED_CHECK = 1, +ACPI_HEST_SOURCE_IA32_NMI = 2, +ACPI_HEST_SOURCE_AER_ROOT_PORT = 6, +ACPI_HEST_SOURCE_AER_ENDPOINT = 7, +ACPI_HEST_SOURCE_AER_BRIDGE = 8, +ACPI_HEST_SOURCE_GENERIC_ERROR = 9, +ACPI_HEST_SOURCE_GENERIC_ERROR_V2 = 10, +ACPI_HEST_SOURCE_RESERVED = 11/* 11 and greater are reserved */ +}; + +/* Block status bitmasks from ACPI 6.1, "18.3.2.7.1 Generic Error Data" */ +#define ACPI_GEBS_UNCORRECTABLE (1) +#define ACPI_GEBS_CORRECTABLE (1 << 1) +#define ACPI_GEBS_MULTIPLE_UNCORRECTABLE(1 << 2) +#define ACPI_GEBS_MULTIPLE_CORRECTABLE (1 << 3) +/* 10 bits, error data entry count */ +#define ACPI_GEBS_ERROR_ENTRY_COUNT (0x3FF << 4) + +/* Generic Hardware Error Source Structure, refer to ACPI 6.1 + * "18.3.2.7 Generic Hardware Error Source". in this struct the + * "type" field has to be ACPI_HEST_SOURCE_GENERIC_ERROR + */ + +struct AcpiGenericHardwareErrorSource { +uint16_t type; +uint16_t source_id; +uint16_t related_source_id; +uint8_t flags; +uint8_t enabled; +uint32_t number_of_records; +uint32_t max_sections_per_record; +uint32_t max_raw_data_length; +struct AcpiGenericAddress error_status_address; +struct AcpiHestNotify notify; +uint32_t error_status_block_length; +} QEMU_PACKED; +typedef struct AcpiGenericHardwareErrorSource AcpiGenericHardwareErrorSource; + +/* Generic Hardware Error Source, version 2, ACPI 6.1, &q
[PATCH v11 6/6] target-arm: kvm64: Handle SError interrupt for the guest OS
When guest OS happens SError interrupt(SEI), it will trap to host. Host firstly calls memory failure to deal with this error and decide whether it needs to deliver SIGBUS signal to userspace. The advantage that using signal to notify is that it can make the notification method is general, non-KVM user can also use it. when userspace gets this signal and knows this is SError interrupt, it will translate the delivered host VA to PA and record this PA to GHES. Because ARMv8.2 adds an extension to RAS to allow system software insert implicit Error Synchronization Barrier operations to isolate the error and allow passes specified syndrome to guest OS, so after record the CPER, user space calls IOCTL to pass a specified syndrome to KVM, then switch to guest OS, guest OS can use the recorded CPER record and syndrome information to do the recovery. The steps are shown below: 1. translate the host VA to guest OS PA and record this error PA to HEST table. 2. set specified virtual SError syndrome and pass the value to KVM. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- linux-headers/linux/kvm.h | 1 + target/arm/internals.h| 1 + target/arm/kvm64.c| 28 3 files changed, 30 insertions(+) diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index 2aa176e..10dfcab 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -1356,6 +1356,7 @@ struct kvm_s390_ucas_mapping { /* Available with KVM_CAP_S390_CMMA_MIGRATION */ #define KVM_S390_GET_CMMA_BITS _IOWR(KVMIO, 0xb8, struct kvm_s390_cmma_log) #define KVM_S390_SET_CMMA_BITS _IOW(KVMIO, 0xb9, struct kvm_s390_cmma_log) +#define KVM_ARM_SEI _IO(KVMIO, 0xb10) #define KVM_DEV_ASSIGN_ENABLE_IOMMU(1 << 0) #define KVM_DEV_ASSIGN_PCI_2_3 (1 << 1) diff --git a/target/arm/internals.h b/target/arm/internals.h index fc0ad6d..18b1cbc 100644 --- a/target/arm/internals.h +++ b/target/arm/internals.h @@ -237,6 +237,7 @@ enum arm_exception_class { #define ARM_EL_ISV (1 << ARM_EL_ISV_SHIFT) #define ARM_EL_EC_MASK ((0x3F) << ARM_EL_EC_SHIFT) #define ARM_EL_FSC_TYPE (0x3C) +#define ARM_EL_ISS_MASK ((1 << ARM_EL_IL_SHIFT) - 1) #define FSC_SEA (0x10) #define FSC_SEA_TTW0(0x14) diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index d3bdab2..b84cb49 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -616,6 +616,22 @@ static int kvm_arm_cpreg_value(ARMCPU *cpu, ptrdiff_t fieldoffset) return -EINVAL; } +static int kvm_inject_arm_sei(CPUState *cs) +{ +ARMCPU *cpu = ARM_CPU(cs); +CPUARMState *env = &cpu->env; + +unsigned long syndrome = env->exception.vaddress; +/* set virtual SError syndrome */ +if (arm_feature(env, ARM_FEATURE_RAS_EXTENSION)) { +syndrome = syndrome & ARM_EL_ISS_MASK; +} else { +syndrome = 0; +} + +return kvm_vcpu_ioctl(CPU(cpu), KVM_ARM_SEI, &syndrome); +} + /* Inject synchronous external abort */ static int kvm_inject_arm_sea(CPUState *c) { @@ -1007,6 +1023,15 @@ static bool is_abort_sea(unsigned long syndrome) } } +static bool is_abort_sei(unsigned long syndrome) +{ +uint8_t ec = ((syndrome & ARM_EL_EC_MASK) >> ARM_EL_EC_SHIFT); +if ((ec != EC_SERROR)) +return false; +else +return true; +} + void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) { ram_addr_t ram_addr; @@ -1024,6 +1049,9 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) if (is_abort_sea(env->exception.syndrome)) { ghes_update_guest(ACPI_HEST_NOTIFY_SEA, paddr); kvm_inject_arm_sea(c); +} else if (is_abort_sei(env->exception.syndrome)) { +ghes_update_guest(ACPI_HEST_NOTIFY_SEI, paddr); +kvm_inject_arm_sei(c); } return; } -- 1.8.3.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v5 4/7] support user space to query RAS extension feature
In armv8.2 RAS extension, it adds virtual SError exception syndrome registeri(VSESR_EL2), user space will specify that value. so user space will check whether CPU feature has RAS extension. if has, it will specify the virtual SError syndrome value. Otherwise, it will not set. This patch adds this support Signed-off-by: Dongjiu Geng --- arch/arm64/kvm/reset.c | 3 +++ include/uapi/linux/kvm.h | 1 + 2 files changed, 4 insertions(+) diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 3256b9228e75..b7313ee028e9 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -77,6 +77,9 @@ int kvm_arch_dev_ioctl_check_extension(struct kvm *kvm, long ext) case KVM_CAP_ARM_PMU_V3: r = kvm_arm_support_pmu_v3(); break; + case KVM_CAP_ARM_RAS_EXTENSION: + r = cpus_have_const_cap(ARM64_HAS_RAS_EXTN); + break; case KVM_CAP_SET_GUEST_DEBUG: case KVM_CAP_VCPU_ATTRIBUTES: r = 1; diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h index 6cd63c18708a..5a2a338cae57 100644 --- a/include/uapi/linux/kvm.h +++ b/include/uapi/linux/kvm.h @@ -929,6 +929,7 @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_PPC_SMT_POSSIBLE 147 #define KVM_CAP_HYPERV_SYNIC2 148 #define KVM_CAP_HYPERV_VP_INDEX 149 +#define KVM_CAP_ARM_RAS_EXTENSION 150 #ifdef KVM_CAP_IRQ_ROUTING -- 2.14.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v5 3/7] acpi: apei: Add SEI notification type support for ARMv8
ARMV8.2 requires implementation of the RAS extension, in this extension it adds SEI(SError Interrupt) notification type, this patch addes a new GHES error source handling function for SEI. Because this error source parse and handling method are similar with the SEA. so use one function to handle them. In current code logic, The two functions ghes_sea_add() and ghes_sea_remove() are only called when CONFIG_ACPI_APEI_SEA and CONFIG_ACPI_APEI_SEI are defined. If not, it will return errors in the ghes_probe() and do not continue, so remove the useless code that handling CONFIG_ACPI_APEI_SEA and CONFIG_ACPI_APEI_SEI do not defined. Expose one API ghes_notify_sex() to external, external modules can call this exposed APIs to parse and handling the SEA/SEI. Signed-off-by: Dongjiu Geng --- arch/arm64/mm/fault.c | 21 +++-- drivers/acpi/apei/Kconfig | 15 drivers/acpi/apei/ghes.c | 60 ++- include/acpi/ghes.h | 2 +- 4 files changed, 74 insertions(+), 24 deletions(-) diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 2509e4fe6992..0aa92a69c280 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -585,7 +585,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs) if (interrupts_enabled(regs)) nmi_enter(); - ret = ghes_notify_sea(); + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEA); if (interrupts_enabled(regs)) nmi_exit(); @@ -682,7 +682,24 @@ int handle_guest_sea(phys_addr_t addr, unsigned int esr) int ret = -ENOENT; if (IS_ENABLED(CONFIG_ACPI_APEI_SEA)) - ret = ghes_notify_sea(); + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEA); + + return ret; +} + +/* + * Handle SError interrupt that occur in a guest kernel. + * + * The return value will be zero if the SEI was successfully handled + * and non-zero if there was an error processing the error or there was + * no error to process. + */ +int handle_guest_sei(phys_addr_t addr, unsigned int esr) +{ + int ret = -ENOENT; + + if (IS_ENABLED(CONFIG_ACPI_APEI_SEI)) + ret = ghes_notify_sex(ACPI_HEST_NOTIFY_SEI); return ret; } diff --git a/drivers/acpi/apei/Kconfig b/drivers/acpi/apei/Kconfig index de14d49a5c90..556370c763ec 100644 --- a/drivers/acpi/apei/Kconfig +++ b/drivers/acpi/apei/Kconfig @@ -54,6 +54,21 @@ config ACPI_APEI_SEA option allows the OS to look for such hardware error record, and take appropriate action. +config ACPI_APEI_SEI + bool "APEI Asynchronous SError Interrupt logging/recovering support" + depends on ARM64 && ACPI_APEI_GHES + default y + help + This option should be enabled if the system supports + firmware first handling of SEI (asynchronous SError interrupt). + + SEI happens with invalid instruction access or asynchronous exceptions + on ARMv8 systems. If a system supports firmware first handling of SEI, + the platform analyzes and handles hardware error notifications from + SEI, and it may then form a HW error record for the OS to parse and + handle. This option allows the OS to look for such hardware error + record, and take appropriate action. + config ACPI_APEI_MEMORY_FAILURE bool "APEI memory error recovering support" depends on ACPI_APEI && MEMORY_FAILURE diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c index d661d452b238..705738aa48b8 100644 --- a/drivers/acpi/apei/ghes.c +++ b/drivers/acpi/apei/ghes.c @@ -813,20 +813,21 @@ static struct notifier_block ghes_notifier_hed = { .notifier_call = ghes_notify_hed, }; -#ifdef CONFIG_ACPI_APEI_SEA static LIST_HEAD(ghes_sea); +static LIST_HEAD(ghes_sei); /* * Return 0 only if one of the SEA error sources successfully reported an error * record sent from the firmware. */ -int ghes_notify_sea(void) + +int ghes_handle_sex(struct list_head *head) { struct ghes *ghes; int ret = -ENOENT; rcu_read_lock(); - list_for_each_entry_rcu(ghes, &ghes_sea, list) { + list_for_each_entry_rcu(ghes, head, list) { if (!ghes_proc(ghes)) ret = 0; } @@ -834,33 +835,41 @@ int ghes_notify_sea(void) return ret; } -static void ghes_sea_add(struct ghes *ghes) +int ghes_notify_sex(u8 type) +{ + if (type == ACPI_HEST_NOTIFY_SEA) + return ghes_handle_sex(&ghes_sea); + else if (type == ACPI_HEST_NOTIFY_SEI) + return ghes_handle_sex(&ghes_sei); + + return -ENOENT; +} + +/* + * This function is only called when the CONFIG_HAVE_ACPI_APEI_SEA or + * CONFIG_HAVE_ACPI_APEI_SEA is enabled. when disabled, it will return + * error in the ghes_probe + */ +static vo
[PATCH v5 7/7] arm64: kvm: handle SEI notification and inject virtual SError
After receive SError, KVM firstly call memory failure to deal with the Error. If memory failure wants user space to handle it, it will notify user space. This patch adds support to userspace that injects virtual SError with specified syndrome. This syndrome value will be set to the VSESR_EL2. VSESR_EL2 is a new RAS extensions register which provides the syndrome value reported to software on taking a virtual SError interrupt exception. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm/include/asm/kvm_host.h | 2 ++ arch/arm/kvm/guest.c | 5 + arch/arm64/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/kvm/guest.c | 13 + arch/arm64/kvm/handle_exit.c | 21 +++-- arch/arm64/kvm/hyp/switch.c | 14 ++ include/uapi/linux/kvm.h | 2 ++ virt/kvm/arm/arm.c | 7 +++ 11 files changed, 78 insertions(+), 2 deletions(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 127e2dd2e21c..bdb6ea690257 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -244,6 +244,8 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *); int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index); +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome); + static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, unsigned long hyp_stack_ptr, unsigned long vector_ptr) diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index 1e0784ebbfd6..c23df72d9bec 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome) +{ + return 0; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 47983db27de2..74213bd539dc 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault.vsesr_el2; +} + +static inline void kvm_vcpu_set_vsesr(struct kvm_vcpu *vcpu, unsigned long val) +{ + vcpu->arch.fault.vsesr_el2 = val; +} + static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d68630007b14..57b011261597 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -88,6 +88,7 @@ struct kvm_vcpu_fault_info { u32 esr_el2;/* Hyp Syndrom Register */ u64 far_el2;/* Hyp Fault Address Register */ u64 hpfar_el2; /* Hyp IPA Fault Address Register */ + u32 vsesr_el2; /* Virtual SError Exception Syndrome Register */ }; /* @@ -381,6 +382,7 @@ int kvm_arm_vcpu_arch_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); int kvm_arm_vcpu_arch_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome); static inline void __cpu_init_stage2(void) { diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 35b786b43ee4..06059eef0f5d 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -86,6 +86,9 @@ #define REG_PSTATE_PAN_IMM sys_reg(0, 0, 4, 0, 4) #define REG_PSTATE_UAO_IMM sys_reg(0, 0, 4, 0, 3) +/* virtual SError exception syndrome register in armv8.2 */ +#define REG_VSESR_EL2 sys_reg(3, 4, 5, 2, 3) + #define SET_PSTATE_PAN(x) __emit_inst(0xd500 | REG_PSTATE_PAN_IMM | \ (!!x)<<8 | 0x1f) #define SET_PSTATE_UAO(x) __emit_inst(0xd500 | REG_PSTATE_UAO_IMM | \ diff --git a/arch/arm64/include/asm/system_misc.h b/arch/arm64/include/asm/system_misc.h index 07aa8e3c5630..7d07aeb02bc4 100644 --- a/arch/arm64/include/asm/system_misc.h +++ b/arch/arm64/include/asm/system_misc.h @@ -57,6 +57,7 @@ extern void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); }) int handle_guest_sea(phys_addr_t addr, unsigned int esr); +int handle_guest_sei(phys_addr_t addr, unsigned int esr); #endif /* __ASSEMBLY__ */ diff --g
[PATCH v5 1/7] arm64: cpufeature: Detect CPU RAS Extentions
From: Xie XiuQi ARM's v8.2 Extentions add support for Reliability, Availability and Serviceability (RAS). On CPUs with these extensions system software can use additional barriers to isolate errors and determine if faults are pending. Add cpufeature detection and a barrier in the context-switch code. There is no need to use alternatives for this as CPUs that don't support this feature will treat the instruction as a nop. Platform level RAS support may require additional firmware support. Signed-off-by: Xie XiuQi [Rebased, added esb and config option, reworded commit message] Signed-off-by: James Morse --- arch/arm64/Kconfig | 16 arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 ++- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kernel/cpufeature.c | 13 + arch/arm64/kernel/process.c | 3 +++ 6 files changed, 37 insertions(+), 1 deletion(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index dfd908630631..4d87aa963d83 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -960,6 +960,22 @@ config ARM64_UAO regular load/store instructions if the cpu does not implement the feature. +config ARM64_RAS_EXTN + bool "Enable support for RAS CPU Extensions" + default y + help + CPUs that support the Reliability, Availability and Serviceability + (RAS) Extensions, part of ARMv8.2 are able to track faults and + errors, classify them and report them to software. + + On CPUs with these extensions system software can use additional + barriers to determine if faults are pending and read the + classification from a new set of registers. + + Selecting this feature will allow the kernel to use these barriers + and access the new registers if the system supports the extension. + Platform RAS features may additionally depend on firmware support. + endmenu config ARM64_MODULE_CMODEL_LARGE diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 0fe7e43b7fbc..8b0a0eb67625 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -30,6 +30,7 @@ #define isb() asm volatile("isb" : : : "memory") #define dmb(opt) asm volatile("dmb " #opt : : : "memory") #define dsb(opt) asm volatile("dsb " #opt : : : "memory") +#define esb() asm volatile("hint #16" : : : "memory") #define mb() dsb(sy) #define rmb() dsb(ld) diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h index 8d2272c6822c..f93bf77f1f74 100644 --- a/arch/arm64/include/asm/cpucaps.h +++ b/arch/arm64/include/asm/cpucaps.h @@ -39,7 +39,8 @@ #define ARM64_WORKAROUND_QCOM_FALKOR_E1003 18 #define ARM64_WORKAROUND_85892119 #define ARM64_WORKAROUND_CAVIUM_30115 20 +#define ARM64_HAS_RAS_EXTN 21 -#define ARM64_NCAPS21 +#define ARM64_NCAPS22 #endif /* __ASM_CPUCAPS_H */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 248339e4aaf5..35b786b43ee4 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -331,6 +331,7 @@ #define ID_AA64ISAR1_JSCVT_SHIFT 12 /* id_aa64pfr0 */ +#define ID_AA64PFR0_RAS_SHIFT 28 #define ID_AA64PFR0_GIC_SHIFT 24 #define ID_AA64PFR0_ASIMD_SHIFT20 #define ID_AA64PFR0_FP_SHIFT 16 @@ -339,6 +340,7 @@ #define ID_AA64PFR0_EL1_SHIFT 4 #define ID_AA64PFR0_EL0_SHIFT 0 +#define ID_AA64PFR0_RAS_V1 0x1 #define ID_AA64PFR0_FP_NI 0xf #define ID_AA64PFR0_FP_SUPPORTED 0x0 #define ID_AA64PFR0_ASIMD_NI 0xf diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 9f9e0064c8c1..a807ab55ee10 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -124,6 +124,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = { }; static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = { + ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_RAS_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64PFR0_GIC_SHIFT, 4, 0), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI), S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_FP_SHIFT, 4, ID_AA64PFR0_FP_NI), @@ -888,6 +889,18 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .min_field_value = 0, .matches = has_no_fpsimd, }, +#ifdef CONFIG_ARM64_RAS_EXTN + { + .desc = "RAS Extension Support", + .capability = ARM64_HAS_RAS_EXTN, + .def_scope = SCOPE_SYSTEM, + .matches = has_cp
[PATCH v5 5/7] arm64: kvm: route synchronous external abort exceptions to el2
ARMv8.2 adds a new bit HCR_EL2.TEA which controls to route synchronous external aborts to EL2, and add a trap control bit HCR_EL2.TERR which will control to trap all Non-secure EL1&0 error record accesses to EL2. This patch will enable the two bits for the guest OS. when an synchronous abort is generated in the guest OS, it will trap to EL3 firmware, firmware will be according to the HCR_EL2.TEA to decide to jump to hypervisor or host OS. In the guest OS, RAS error record access will trap to EL2. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ 2 files changed, 9 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c2eae5..1188272003c4 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index fe39e6841326..47983db27de2 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } -- 2.14.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v5 2/7] KVM: arm64: Save ESR_EL2 on guest SError
From: James Morse When we exit a guest due to an SError the vcpu fault info isn't updated with the ESR. Today this is only done for traps. The v8.2 RAS Extensions define ISS values for SError. Update the vcpu's fault_info with the ESR on SError so that handle_exit() can determine if this was a RAS SError and decode its severity. Signed-off-by: James Morse --- arch/arm64/kvm/hyp/switch.c | 15 --- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 945e79c641c4..c6f17c7675ad 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -226,13 +226,20 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) return true; } +static void __hyp_text __populate_fault_info_esr(struct kvm_vcpu *vcpu) +{ + vcpu->arch.fault.esr_el2 = read_sysreg_el2(esr); +} + static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) { - u64 esr = read_sysreg_el2(esr); - u8 ec = ESR_ELx_EC(esr); + u8 ec; + u64 esr; u64 hpfar, far; - vcpu->arch.fault.esr_el2 = esr; + __populate_fault_info_esr(vcpu); + esr = vcpu->arch.fault.esr_el2; + ec = ESR_ELx_EC(esr); if (ec != ESR_ELx_EC_DABT_LOW && ec != ESR_ELx_EC_IABT_LOW) return true; @@ -321,6 +328,8 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) */ if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu)) goto again; + else if (ARM_EXCEPTION_CODE(exit_code) == ARM_EXCEPTION_EL1_SERROR) + __populate_fault_info_esr(vcpu); if (static_branch_unlikely(&vgic_v2_cpuif_trap) && exit_code == ARM_EXCEPTION_TRAP) { -- 2.14.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v5 6/7] KVM: arm64: Allow get exception information from userspace
when userspace gets SIGBUS signal, it does not know whether this is a synchronous external abort or SError, so needs to get the exception syndrome. so this patch allows userspace can get this values. For syndrome, only give userspace syndrome EC and ISS. Now we move the synchronous external abort injection logic to userspace, when userspace injects the SEA exception to guest OS, it needs to specify the far_el1 value, so this patch give the exception virtual address to user space. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/uapi/asm/kvm.h | 5 + arch/arm64/kvm/guest.c| 35 +++ 2 files changed, 40 insertions(+) diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 9f3ca24bbcc6..514261f682b8 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -181,6 +181,11 @@ struct kvm_arch_memory_slot { #define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0007 #define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0 +/* AArch64 fault registers */ +#define KVM_REG_ARM64_FAULT(0x0014 << KVM_REG_ARM_COPROC_SHIFT) +#define KVM_REG_ARM64_FAULT_ESR_EC_ISS (0) +#define KVM_REG_ARM64_FAULT_FAR(1) + #define ARM64_SYS_REG_SHIFT_MASK(x,n) \ (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \ KVM_REG_ARM64_SYSREG_ ## n ## _MASK) diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c index 5c7f657dd207..cb383c310f18 100644 --- a/arch/arm64/kvm/guest.c +++ b/arch/arm64/kvm/guest.c @@ -128,6 +128,38 @@ static int set_core_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) out: return err; } +static int get_fault_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) +{ + void __user *uaddr = (void __user *)(unsigned long)reg->addr; + u32 ec, value; + u32 id = reg->id & ~(KVM_REG_ARCH_MASK | + KVM_REG_SIZE_MASK | KVM_REG_ARM64_FAULT); + + switch (id) { + case KVM_REG_ARM64_FAULT_ESR_EC_ISS: + /* The user space needs to know the fault exception +* class field +*/ + ec = kvm_vcpu_get_hsr(vcpu) & ESR_ELx_EC_MASK; + value = ec | (kvm_vcpu_get_hsr(vcpu) & ESR_ELx_ISS_MASK); + + if (copy_to_user(uaddr, &value, KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; + break; + case KVM_REG_ARM64_FAULT_FAR: + /* when user space injects synchronized abort, it needs +* to inject the fault address. +*/ + if (copy_to_user(uaddr, &(vcpu->arch.fault.far_el2), + KVM_REG_SIZE(reg->id)) != 0) + return -EFAULT; + break; + default: + return -ENOENT; + } + return 0; +} + int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) { @@ -243,6 +275,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg) if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE) return get_core_reg(vcpu, reg); + if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM64_FAULT) + return get_fault_reg(vcpu, reg); + if (is_timer_reg(reg->id)) return get_timer_reg(vcpu, reg); -- 2.14.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v5 0/7] Add RAS virtualization support to SEA/SEI notification type
In the firmware-first RAS solution, corrupt data is detected in a memory location when guest OS application software executing at EL0 or guest OS kernel El1 software are reading from the memory. The memory node records errors in an error record accessible using system registers. Because SCR_EL3.EA is 1, then CPU will trap to El3 firmware, EL3 firmware records the error to APEI table through reading system register. Because the error was taken from a lower Exception leve, if the exception is SEA/SEI and HCR_EL2.TEA/HCR_EL2.AMO is 1, firmware sets ESR_EL2/FAR_El to fake a exception trap to EL2, then transfers to hypervisor. Hypervisor calls the momory failure to deal with this error, momory failure read the APEI table and decide whether it needs to deliver SIGBUS signal to user space, the advantage of using SIGBUS signal to notify user space is that it can be compatible Non-Kvm users. Dongjiu Geng (5): acpi: apei: Add SEI notification type support for ARMv8 support user space to query RAS extension feature arm64: kvm: route synchronous external abort exceptions to el2 KVM: arm/arm64: Allow get exception syndrome and arm64: kvm: handle SEI notification and inject virtual SError James Morse (1): KVM: arm64: Save ESR_EL2 on guest SError Xie XiuQi (1): arm64: cpufeature: Detect CPU RAS Extentions arch/arm/include/asm/kvm_host.h | 2 ++ arch/arm/kvm/guest.c | 5 +++ arch/arm64/Kconfig | 16 ++ arch/arm64/include/asm/barrier.h | 1 + arch/arm64/include/asm/cpucaps.h | 3 +- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 17 ++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 5 +++ arch/arm64/include/asm/system_misc.h | 1 + arch/arm64/include/uapi/asm/kvm.h| 5 +++ arch/arm64/kernel/cpufeature.c | 13 arch/arm64/kernel/process.c | 3 ++ arch/arm64/kvm/guest.c | 48 + arch/arm64/kvm/handle_exit.c | 21 +++-- arch/arm64/kvm/hyp/switch.c | 29 +++-- arch/arm64/kvm/reset.c | 3 ++ arch/arm64/mm/fault.c| 21 +++-- drivers/acpi/apei/Kconfig| 15 + drivers/acpi/apei/ghes.c | 60 +++- include/acpi/ghes.h | 2 +- include/uapi/linux/kvm.h | 3 ++ virt/kvm/arm/arm.c | 7 + 23 files changed, 254 insertions(+), 30 deletions(-) -- 2.14.0 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v2] KVM: arm64: pass vcpu esr_el2 and far_el2 sysre to user space
For the firmware-first RAS solution, SEA and SEI is injected by the user space, user space needs to know the vcpu's esr_el2 and far_el2 value, so add them to sysreg. user space uses the IOCTL KVM_GET_ONE_REG can get their value. Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_host.h | 6 -- arch/arm64/include/asm/sysreg.h | 2 ++ arch/arm64/kvm/hyp/switch.c | 2 ++ arch/arm64/kvm/sys_regs.c | 2 ++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index d68630007b14..075ff9fba0af 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -104,10 +104,12 @@ enum vcpu_sysreg { TTBR0_EL1, /* Translation Table Base Register 0 */ TTBR1_EL1, /* Translation Table Base Register 1 */ TCR_EL1,/* Translation Control Register */ - ESR_EL1,/* Exception Syndrome Register */ + ESR_EL1,/* Exception Syndrome Register for EL1 */ + ESR_EL2,/* Exception Syndrome Register for EL2 */ AFSR0_EL1, /* Auxiliary Fault Status Register 0 */ AFSR1_EL1, /* Auxiliary Fault Status Register 1 */ - FAR_EL1,/* Fault Address Register */ + FAR_EL1,/* Fault Address Register for EL1 */ + FAR_EL2,/* Fault Address Register for EL2 */ MAIR_EL1, /* Memory Attribute Indirection Register */ VBAR_EL1, /* Vector Base Address Register */ CONTEXTIDR_EL1, /* Context ID Register */ diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h index 248339e4aaf5..b019141a8c29 100644 --- a/arch/arm64/include/asm/sysreg.h +++ b/arch/arm64/include/asm/sysreg.h @@ -252,7 +252,9 @@ #define SYS_DACR32_EL2 sys_reg(3, 4, 3, 0, 0) #define SYS_IFSR32_EL2 sys_reg(3, 4, 5, 0, 1) +#define SYS_ESR_EL2sys_reg(3, 4, 5, 2, 0) #define SYS_FPEXC32_EL2sys_reg(3, 4, 5, 3, 0) +#define SYS_FAR_EL2sys_reg(3, 4, 6, 0, 0) #define __SYS__AP0Rx_EL2(x)sys_reg(3, 4, 12, 8, x) #define SYS_ICH_AP0R0_EL2 __SYS__AP0Rx_EL2(0) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index c6f17c7675ad..6ec9ecd68d20 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -229,6 +229,7 @@ static bool __hyp_text __translate_far_to_hpfar(u64 far, u64 *hpfar) static void __hyp_text __populate_fault_info_esr(struct kvm_vcpu *vcpu) { vcpu->arch.fault.esr_el2 = read_sysreg_el2(esr); + vcpu_sys_reg(vcpu,ESR_EL2) = read_sysreg_el2(esr); } static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) @@ -267,6 +268,7 @@ static bool __hyp_text __populate_fault_info(struct kvm_vcpu *vcpu) vcpu->arch.fault.far_el2 = far; vcpu->arch.fault.hpfar_el2 = hpfar; + vcpu_sys_reg(vcpu,FAR_EL2) = far; return true; } diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 2e070d3baf9f..c730d593efbb 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1079,7 +1079,9 @@ static const struct sys_reg_desc sys_reg_descs[] = { { SYS_DESC(SYS_DACR32_EL2), NULL, reset_unknown, DACR32_EL2 }, { SYS_DESC(SYS_IFSR32_EL2), NULL, reset_unknown, IFSR32_EL2 }, + { SYS_DESC(SYS_ESR_EL2), access_vm_reg, reset_unknown, ESR_EL2 }, { SYS_DESC(SYS_FPEXC32_EL2), NULL, reset_val, FPEXC32_EL2, 0x70 }, + { SYS_DESC(SYS_FAR_EL2), access_vm_reg, reset_unknown, FAR_EL2 }, }; static bool trap_dbgidr(struct kvm_vcpu *vcpu, -- 2.13.4 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH] KVM: arm64: add esr_el2 and far_el2 to sysreg
For the firmware-first RAS solution, SEA and SEI is injected by the user space, user space needs to know the esr_el2 and far_el2's value, so add them to sysreg. user space uses the IOCTL KVM_GET_ONE_REG can get their value. Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- arch/arm64/include/asm/kvm_host.h | 6 -- arch/arm64/kvm/sys_regs.c | 6 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index b6242fb..6063eec 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -103,10 +103,12 @@ enum vcpu_sysreg { TTBR0_EL1, /* Translation Table Base Register 0 */ TTBR1_EL1, /* Translation Table Base Register 1 */ TCR_EL1,/* Translation Control Register */ - ESR_EL1,/* Exception Syndrome Register */ + ESR_EL1,/* Exception Syndrome Register for EL1 */ + ESR_EL2,/* Exception Syndrome Register for EL2 */ AFSR0_EL1, /* Auxiliary Fault Status Register 0 */ AFSR1_EL1, /* Auxiliary Fault Status Register 1 */ - FAR_EL1,/* Fault Address Register */ + FAR_EL1,/* Fault Address Register for EL1 */ + FAR_EL2,/* Fault Address Register for EL2 */ MAIR_EL1, /* Memory Attribute Indirection Register */ VBAR_EL1, /* Vector Base Address Register */ CONTEXTIDR_EL1, /* Context ID Register */ diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 0e26f8c..0c286bf 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -987,9 +987,15 @@ static const struct sys_reg_desc sys_reg_descs[] = { /* ESR_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b0101), CRm(0b0010), Op2(0b000), access_vm_reg, reset_unknown, ESR_EL1 }, + /* ESR_EL2 */ + { Op0(0b11), Op1(0b100), CRn(0b0101), CRm(0b0010), Op2(0b000), + access_vm_reg, reset_unknown, ESR_EL2 }, /* FAR_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b0110), CRm(0b), Op2(0b000), access_vm_reg, reset_unknown, FAR_EL1 }, + /* FAR_EL2 */ + { Op0(0b11), Op1(0b100), CRn(0b0110), CRm(0b), Op2(0b000), + access_vm_reg, reset_unknown, FAR_EL2 }, /* PAR_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b0111), CRm(0b0100), Op2(0b000), NULL, reset_unknown, PAR_EL1 }, -- 2.10.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
[PATCH v4 3/3] arm64: kvm: inject SError with user space specified syndrome
when SError happen, kvm notifies user space to record the CPER, user space specifies and passes the contents of ESR_EL1 on taking a virtual SError interrupt to KVM, KVM enables virtual system error or asynchronous abort with this specifies syndrome. This patch modify the world-switch to restore VSESR_EL2, VSESR_EL2 saves the virtual SError syndrome, it becomes the ESR_EL1 value when HCR_EL2.VSE injects an SError. This register is added by the RAS Extensions. Changes since v3: (1) Move restore VSESR_EL2 value logic to a helper method (2) In the world-switch, not save VSESR_EL2, because no one cares the old VSESR_EL2 value (3) Add a new KVM_ARM_SEI ioctl to set the VSESR_EL2 value and pend a virtual system error Signed-off-by: Dongjiu Geng Signed-off-by: Quanming Wu --- Documentation/virtual/kvm/api.txt| 10 ++ arch/arm/include/asm/kvm_host.h | 1 + arch/arm/kvm/arm.c | 7 +++ arch/arm/kvm/guest.c | 5 + arch/arm64/include/asm/esr.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 10 ++ arch/arm64/include/asm/kvm_host.h| 2 ++ arch/arm64/include/asm/sysreg.h | 3 +++ arch/arm64/kvm/guest.c | 14 ++ arch/arm64/kvm/handle_exit.c | 25 +++-- arch/arm64/kvm/hyp/switch.c | 14 ++ include/uapi/linux/kvm.h | 8 12 files changed, 95 insertions(+), 6 deletions(-) diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 3c248f7..852ac55 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt @@ -3377,6 +3377,16 @@ struct kvm_ppc_resize_hpt { __u32 pad; }; +4.104 KVM_ARM_SEI + +Capability: KVM_EXIT_SERROR_INTR +Architectures: arm/arm64 +Type: vcpu ioctl +Parameters: u64 (syndrome) +Returns: 0 in case of success + +Pend an virtual system error or asynchronous abort with user space specified. + 5. The kvm_run structure diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index 31ee468..566292a 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -244,6 +244,7 @@ int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *); int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run, int exception_index); +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome); static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr, unsigned long hyp_stack_ptr, diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 96dba7c..583294f 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -987,6 +987,13 @@ long kvm_arch_vcpu_ioctl(struct file *filp, return -EFAULT; return kvm_arm_vcpu_has_attr(vcpu, &attr); } + case KVM_ARM_SEI: { + u64 syndrome; + + if (copy_from_user(&syndrome, argp, sizeof(syndrome))) + return -EFAULT; + return kvm_vcpu_ioctl_sei(vcpu, &syndrome); + } default: return -EINVAL; } diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c index fa6182a..72505bf 100644 --- a/arch/arm/kvm/guest.c +++ b/arch/arm/kvm/guest.c @@ -248,6 +248,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, return -EINVAL; } +int kvm_vcpu_ioctl_sei(struct kvm_vcpu *vcpu, u64 *syndrome) +{ + return 0; +} + int __attribute_const__ kvm_target_cpu(void) { switch (read_cpuid_part()) { diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h index 22f9c90..d009c99 100644 --- a/arch/arm64/include/asm/esr.h +++ b/arch/arm64/include/asm/esr.h @@ -127,6 +127,8 @@ #define ESR_ELx_WFx_ISS_WFE(UL(1) << 0) #define ESR_ELx_xVC_IMM_MASK ((1UL << 16) - 1) +#define VSESR_ELx_IDS_ISS_MASK((1UL << 25) - 1) + /* ESR value templates for specific events */ /* BRK instruction trap from AArch64 state */ diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index 5f64ab2..93dc3d1 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -155,6 +155,16 @@ static inline u32 kvm_vcpu_get_hsr(const struct kvm_vcpu *vcpu) return vcpu->arch.fault.esr_el2; } +static inline u32 kvm_vcpu_get_vsesr(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.fault.vsesr_el2; +} + +static inline void kvm_vcpu_set_vsesr(struct kvm_vcpu *vcpu, unsigned long val) +{ + vcpu->arch.fault.vsesr_el2 = val; +} + static inline int kvm_vcpu_get_condition(const struct kvm_vcpu *vcpu) { u32 esr = kvm_vcpu_get_hsr(vcpu); diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index e7705e7..b6242fb 100644 --- a/arch/arm64/include/asm/
[PATCH v4 2/3] arm64: kvm: route synchronous external abort exceptions to el2
In the firmware-first RAS solution, guest OS receives an synchronous external abort, then trapped to EL3 by SCR_EL3.EA. Firmware inspects the HCR_EL2.TEA and chooses the target to send APEI's SEA notification. If the SCR_EL3.EA is set, delegates the error exception to the hypervisor, otherwise it delegates to the guest OS kernel Signed-off-by: Dongjiu Geng --- arch/arm64/include/asm/kvm_arm.h | 2 ++ arch/arm64/include/asm/kvm_emulate.h | 7 +++ 2 files changed, 9 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 61d694c..1188272 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -23,6 +23,8 @@ #include /* Hyp Configuration Register (HCR) bits */ +#define HCR_TEA(UL(1) << 37) +#define HCR_TERR (UL(1) << 36) #define HCR_E2H(UL(1) << 34) #define HCR_ID (UL(1) << 33) #define HCR_CD (UL(1) << 32) diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h index f5ea0ba..5f64ab2 100644 --- a/arch/arm64/include/asm/kvm_emulate.h +++ b/arch/arm64/include/asm/kvm_emulate.h @@ -47,6 +47,13 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu) vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS; if (is_kernel_in_hyp_mode()) vcpu->arch.hcr_el2 |= HCR_E2H; + if (cpus_have_const_cap(ARM64_HAS_RAS_EXTN)) { + /* route synchronous external abort exceptions to EL2 */ + vcpu->arch.hcr_el2 |= HCR_TEA; + /* trap error record accesses */ + vcpu->arch.hcr_el2 |= HCR_TERR; + } + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) vcpu->arch.hcr_el2 &= ~HCR_RW; } -- 2.10.1 ___ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm