From 665069da1f6cafe30100118e93950c70b868c2d3 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Fri, 9 Jun 2017 12:49:56 +0100 Subject: [PATCH] KVM: arm64: Log an error if trapping a write-to-read-only GICv3 access BugLink: https://bugs.launchpad.net/bugs/1673564 A write-to-read-only GICv3 access should UNDEF at EL1. But since we're in complete paranoia-land with broken CPUs, let's assume the worse and gracefully handle the case. Signed-off-by: Marc Zyngier Reviewed-by: Christoffer Dall Signed-off-by: Christoffer Dall (backported picked from commit 7b1dba1f7325629427c0e5bdf014159b229d16c8) [ dannf: Recoded sys_reg_descs[] entries to use pre-SYS_DESC() syntax and minor context changes. ] Signed-off-by: dann frazier Acked-by: Stefan Bader Acked-by: Kleber Sacilotto de Souza Signed-off-by: Kleber Sacilotto de Souza --- arch/arm64/kvm/sys_regs.c | 25 +++++++++++++++++++++++++ virt/kvm/arm/hyp/vgic-v3-sr.c | 6 ++++++ 2 files changed, 31 insertions(+) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 467420397729..6808defa3da8 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -65,6 +65,16 @@ static bool read_from_write_only(struct kvm_vcpu *vcpu, return false; } +static bool write_to_read_only(struct kvm_vcpu *vcpu, + struct sys_reg_params *params, + const struct sys_reg_desc *r) +{ + WARN_ONCE(1, "Unexpected sys_reg write to read-only register\n"); + print_sys_reg_instr(params); + kvm_inject_undefined(vcpu); + return false; +} + /* 3 bits per cache level, as per CLIDR, but non-existent caches always 0 */ static u32 cache_levels; @@ -967,18 +977,33 @@ static const struct sys_reg_desc sys_reg_descs[] = { { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b0000), Op2(0b000), NULL, reset_val, VBAR_EL1, 0 }, + /* ICC_IAR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1000), Op2(0b000), + write_to_read_only }, /* ICC_EOIR0_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1000), Op2(0b001), read_from_write_only }, + /* ICC_HPPIR0_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1000), Op2(0b010), + write_to_read_only }, /* ICC_DIR_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b001), read_from_write_only }, + /* ICC_RPR_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b011), + write_to_read_only }, /* ICC_SGI1R_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1011), Op2(0b101), access_gic_sgi }, + /* ICC_IAR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b000), + write_to_read_only }, /* ICC_EOIR1_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b001), read_from_write_only }, + /* ICC_HPPIR1_EL1 */ + { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b010), + write_to_read_only }, /* ICC_SRE_EL1 */ { Op0(0b11), Op1(0b000), CRn(0b1100), CRm(0b1100), Op2(0b101), access_gic_sre }, diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c index 773ebe5466e0..2164ed639139 100644 --- a/virt/kvm/arm/hyp/vgic-v3-sr.c +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c @@ -1025,6 +1025,8 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) switch (sysreg) { case ICC_IAR0_EL1: case ICC_IAR1_EL1: + if (unlikely(!is_read)) + return 0; fn = __vgic_v3_read_iar; break; case ICC_EOIR0_EL1: @@ -1075,6 +1077,8 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) break; case ICC_HPPIR0_EL1: case ICC_HPPIR1_EL1: + if (unlikely(!is_read)) + return 0; fn = __vgic_v3_read_hppir; break; case ICC_GRPEN0_EL1: @@ -1095,6 +1099,8 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu) fn = __vgic_v3_write_dir; break; case ICC_RPR_EL1: + if (unlikely(!is_read)) + return 0; fn = __vgic_v3_read_rpr; break; case ICC_CTLR_EL1: -- 2.39.5