diff options
-rw-r--r-- | arch/arm64/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/arm64/kvm/vgic-v3-switch.S | 14 | ||||
-rw-r--r-- | include/kvm/arm_vgic.h | 1 | ||||
-rw-r--r-- | virt/kvm/arm/vgic-v3.c | 8 |
4 files changed, 17 insertions, 7 deletions
diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index 9a9fce090d58..9d34486985fd 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c | |||
@@ -140,6 +140,7 @@ int main(void) | |||
140 | DEFINE(VGIC_V2_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr)); | 140 | DEFINE(VGIC_V2_CPU_ELRSR, offsetof(struct vgic_cpu, vgic_v2.vgic_elrsr)); |
141 | DEFINE(VGIC_V2_CPU_APR, offsetof(struct vgic_cpu, vgic_v2.vgic_apr)); | 141 | DEFINE(VGIC_V2_CPU_APR, offsetof(struct vgic_cpu, vgic_v2.vgic_apr)); |
142 | DEFINE(VGIC_V2_CPU_LR, offsetof(struct vgic_cpu, vgic_v2.vgic_lr)); | 142 | DEFINE(VGIC_V2_CPU_LR, offsetof(struct vgic_cpu, vgic_v2.vgic_lr)); |
143 | DEFINE(VGIC_V3_CPU_SRE, offsetof(struct vgic_cpu, vgic_v3.vgic_sre)); | ||
143 | DEFINE(VGIC_V3_CPU_HCR, offsetof(struct vgic_cpu, vgic_v3.vgic_hcr)); | 144 | DEFINE(VGIC_V3_CPU_HCR, offsetof(struct vgic_cpu, vgic_v3.vgic_hcr)); |
144 | DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr)); | 145 | DEFINE(VGIC_V3_CPU_VMCR, offsetof(struct vgic_cpu, vgic_v3.vgic_vmcr)); |
145 | DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr)); | 146 | DEFINE(VGIC_V3_CPU_MISR, offsetof(struct vgic_cpu, vgic_v3.vgic_misr)); |
diff --git a/arch/arm64/kvm/vgic-v3-switch.S b/arch/arm64/kvm/vgic-v3-switch.S index d16046999e06..617a012a0107 100644 --- a/arch/arm64/kvm/vgic-v3-switch.S +++ b/arch/arm64/kvm/vgic-v3-switch.S | |||
@@ -148,17 +148,18 @@ | |||
148 | * x0: Register pointing to VCPU struct | 148 | * x0: Register pointing to VCPU struct |
149 | */ | 149 | */ |
150 | .macro restore_vgic_v3_state | 150 | .macro restore_vgic_v3_state |
151 | // Disable SRE_EL1 access. Necessary, otherwise | ||
152 | // ICH_VMCR_EL2.VFIQEn becomes one, and FIQ happens... | ||
153 | msr_s ICC_SRE_EL1, xzr | ||
154 | isb | ||
155 | |||
156 | // Compute the address of struct vgic_cpu | 151 | // Compute the address of struct vgic_cpu |
157 | add x3, x0, #VCPU_VGIC_CPU | 152 | add x3, x0, #VCPU_VGIC_CPU |
158 | 153 | ||
159 | // Restore all interesting registers | 154 | // Restore all interesting registers |
160 | ldr w4, [x3, #VGIC_V3_CPU_HCR] | 155 | ldr w4, [x3, #VGIC_V3_CPU_HCR] |
161 | ldr w5, [x3, #VGIC_V3_CPU_VMCR] | 156 | ldr w5, [x3, #VGIC_V3_CPU_VMCR] |
157 | ldr w25, [x3, #VGIC_V3_CPU_SRE] | ||
158 | |||
159 | msr_s ICC_SRE_EL1, x25 | ||
160 | |||
161 | // make sure SRE is valid before writing the other registers | ||
162 | isb | ||
162 | 163 | ||
163 | msr_s ICH_HCR_EL2, x4 | 164 | msr_s ICH_HCR_EL2, x4 |
164 | msr_s ICH_VMCR_EL2, x5 | 165 | msr_s ICH_VMCR_EL2, x5 |
@@ -244,9 +245,12 @@ | |||
244 | dsb sy | 245 | dsb sy |
245 | 246 | ||
246 | // Prevent the guest from touching the GIC system registers | 247 | // Prevent the guest from touching the GIC system registers |
248 | // if SRE isn't enabled for GICv3 emulation | ||
249 | cbnz x25, 1f | ||
247 | mrs_s x5, ICC_SRE_EL2 | 250 | mrs_s x5, ICC_SRE_EL2 |
248 | and x5, x5, #~ICC_SRE_EL2_ENABLE | 251 | and x5, x5, #~ICC_SRE_EL2_ENABLE |
249 | msr_s ICC_SRE_EL2, x5 | 252 | msr_s ICC_SRE_EL2, x5 |
253 | 1: | ||
250 | .endm | 254 | .endm |
251 | 255 | ||
252 | ENTRY(__save_vgic_v3_state) | 256 | ENTRY(__save_vgic_v3_state) |
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 1c0e9dbabe6d..ff04afd0d901 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h | |||
@@ -245,6 +245,7 @@ struct vgic_v3_cpu_if { | |||
245 | #ifdef CONFIG_ARM_GIC_V3 | 245 | #ifdef CONFIG_ARM_GIC_V3 |
246 | u32 vgic_hcr; | 246 | u32 vgic_hcr; |
247 | u32 vgic_vmcr; | 247 | u32 vgic_vmcr; |
248 | u32 vgic_sre; /* Restored only, change ignored */ | ||
248 | u32 vgic_misr; /* Saved only */ | 249 | u32 vgic_misr; /* Saved only */ |
249 | u32 vgic_eisr; /* Saved only */ | 250 | u32 vgic_eisr; /* Saved only */ |
250 | u32 vgic_elrsr; /* Saved only */ | 251 | u32 vgic_elrsr; /* Saved only */ |
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index ea39bad4b004..52490480b6f9 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c | |||
@@ -145,15 +145,19 @@ static void vgic_v3_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) | |||
145 | 145 | ||
146 | static void vgic_v3_enable(struct kvm_vcpu *vcpu) | 146 | static void vgic_v3_enable(struct kvm_vcpu *vcpu) |
147 | { | 147 | { |
148 | struct vgic_v3_cpu_if *vgic_v3 = &vcpu->arch.vgic_cpu.vgic_v3; | ||
149 | |||
148 | /* | 150 | /* |
149 | * By forcing VMCR to zero, the GIC will restore the binary | 151 | * By forcing VMCR to zero, the GIC will restore the binary |
150 | * points to their reset values. Anything else resets to zero | 152 | * points to their reset values. Anything else resets to zero |
151 | * anyway. | 153 | * anyway. |
152 | */ | 154 | */ |
153 | vcpu->arch.vgic_cpu.vgic_v3.vgic_vmcr = 0; | 155 | vgic_v3->vgic_vmcr = 0; |
156 | |||
157 | vgic_v3->vgic_sre = 0; | ||
154 | 158 | ||
155 | /* Get the show on the road... */ | 159 | /* Get the show on the road... */ |
156 | vcpu->arch.vgic_cpu.vgic_v3.vgic_hcr = ICH_HCR_EN; | 160 | vgic_v3->vgic_hcr = ICH_HCR_EN; |
157 | } | 161 | } |
158 | 162 | ||
159 | static const struct vgic_ops vgic_v3_ops = { | 163 | static const struct vgic_ops vgic_v3_ops = { |