diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2015-09-14 11:07:35 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2015-09-14 11:07:35 -0400 |
commit | 51256484c033a6d57d71aa8f788c24e5dc82348a (patch) | |
tree | d6ce14cf9d5c1ae9fd6b5aac055d66fad0e1792f | |
parent | edb9272f35d8bc97c86101a13f67d0ba16f3eecc (diff) | |
parent | 0c0672922dcc70ffba11d96385e98e42fb3ae08d (diff) |
Merge tag 'kvm-arm-for-4.3-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into kvm-master
KVM/ARM changes for 4.3-rc2
- Fix timer interrupt injection after the rework
that went in during the merge window
- Reset the timer to zero on reboot
- Make sure the TCR_EL2 RES1 bits are really set to 1
- Fix a PSCI affinity bug for non-existing vcpus
-rw-r--r-- | arch/arm/kvm/psci.c | 12 | ||||
-rw-r--r-- | arch/arm64/include/asm/kvm_arm.h | 10 | ||||
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 8 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 42 |
4 files changed, 49 insertions, 23 deletions
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c index 4b94b513168d..ad6f6424f1d1 100644 --- a/arch/arm/kvm/psci.c +++ b/arch/arm/kvm/psci.c | |||
@@ -126,7 +126,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) | |||
126 | 126 | ||
127 | static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) | 127 | static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) |
128 | { | 128 | { |
129 | int i; | 129 | int i, matching_cpus = 0; |
130 | unsigned long mpidr; | 130 | unsigned long mpidr; |
131 | unsigned long target_affinity; | 131 | unsigned long target_affinity; |
132 | unsigned long target_affinity_mask; | 132 | unsigned long target_affinity_mask; |
@@ -151,12 +151,16 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) | |||
151 | */ | 151 | */ |
152 | kvm_for_each_vcpu(i, tmp, kvm) { | 152 | kvm_for_each_vcpu(i, tmp, kvm) { |
153 | mpidr = kvm_vcpu_get_mpidr_aff(tmp); | 153 | mpidr = kvm_vcpu_get_mpidr_aff(tmp); |
154 | if (((mpidr & target_affinity_mask) == target_affinity) && | 154 | if ((mpidr & target_affinity_mask) == target_affinity) { |
155 | !tmp->arch.pause) { | 155 | matching_cpus++; |
156 | return PSCI_0_2_AFFINITY_LEVEL_ON; | 156 | if (!tmp->arch.pause) |
157 | return PSCI_0_2_AFFINITY_LEVEL_ON; | ||
157 | } | 158 | } |
158 | } | 159 | } |
159 | 160 | ||
161 | if (!matching_cpus) | ||
162 | return PSCI_RET_INVALID_PARAMS; | ||
163 | |||
160 | return PSCI_0_2_AFFINITY_LEVEL_OFF; | 164 | return PSCI_0_2_AFFINITY_LEVEL_OFF; |
161 | } | 165 | } |
162 | 166 | ||
diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 7605e095217f..cbc5e1a0ea8f 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h | |||
@@ -95,6 +95,7 @@ | |||
95 | SCTLR_EL2_SA | SCTLR_EL2_I) | 95 | SCTLR_EL2_SA | SCTLR_EL2_I) |
96 | 96 | ||
97 | /* TCR_EL2 Registers bits */ | 97 | /* TCR_EL2 Registers bits */ |
98 | #define TCR_EL2_RES1 ((1 << 31) | (1 << 23)) | ||
98 | #define TCR_EL2_TBI (1 << 20) | 99 | #define TCR_EL2_TBI (1 << 20) |
99 | #define TCR_EL2_PS (7 << 16) | 100 | #define TCR_EL2_PS (7 << 16) |
100 | #define TCR_EL2_PS_40B (2 << 16) | 101 | #define TCR_EL2_PS_40B (2 << 16) |
@@ -106,9 +107,10 @@ | |||
106 | #define TCR_EL2_MASK (TCR_EL2_TG0 | TCR_EL2_SH0 | \ | 107 | #define TCR_EL2_MASK (TCR_EL2_TG0 | TCR_EL2_SH0 | \ |
107 | TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ) | 108 | TCR_EL2_ORGN0 | TCR_EL2_IRGN0 | TCR_EL2_T0SZ) |
108 | 109 | ||
109 | #define TCR_EL2_FLAGS (TCR_EL2_PS_40B) | 110 | #define TCR_EL2_FLAGS (TCR_EL2_RES1 | TCR_EL2_PS_40B) |
110 | 111 | ||
111 | /* VTCR_EL2 Registers bits */ | 112 | /* VTCR_EL2 Registers bits */ |
113 | #define VTCR_EL2_RES1 (1 << 31) | ||
112 | #define VTCR_EL2_PS_MASK (7 << 16) | 114 | #define VTCR_EL2_PS_MASK (7 << 16) |
113 | #define VTCR_EL2_TG0_MASK (1 << 14) | 115 | #define VTCR_EL2_TG0_MASK (1 << 14) |
114 | #define VTCR_EL2_TG0_4K (0 << 14) | 116 | #define VTCR_EL2_TG0_4K (0 << 14) |
@@ -147,7 +149,8 @@ | |||
147 | */ | 149 | */ |
148 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \ | 150 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_64K | VTCR_EL2_SH0_INNER | \ |
149 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ | 151 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ |
150 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) | 152 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \ |
153 | VTCR_EL2_RES1) | ||
151 | #define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) | 154 | #define VTTBR_X (38 - VTCR_EL2_T0SZ_40B) |
152 | #else | 155 | #else |
153 | /* | 156 | /* |
@@ -158,7 +161,8 @@ | |||
158 | */ | 161 | */ |
159 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \ | 162 | #define VTCR_EL2_FLAGS (VTCR_EL2_TG0_4K | VTCR_EL2_SH0_INNER | \ |
160 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ | 163 | VTCR_EL2_ORGN0_WBWA | VTCR_EL2_IRGN0_WBWA | \ |
161 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B) | 164 | VTCR_EL2_SL0_LVL1 | VTCR_EL2_T0SZ_40B | \ |
165 | VTCR_EL2_RES1) | ||
162 | #define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) | 166 | #define VTTBR_X (37 - VTCR_EL2_T0SZ_40B) |
163 | #endif | 167 | #endif |
164 | 168 | ||
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 76e38d231e99..48c6e1ac6827 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -200,6 +200,14 @@ int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | |||
200 | timer->irq = irq; | 200 | timer->irq = irq; |
201 | 201 | ||
202 | /* | 202 | /* |
203 | * The bits in CNTV_CTL are architecturally reset to UNKNOWN for ARMv8 | ||
204 | * and to 0 for ARMv7. We provide an implementation that always | ||
205 | * resets the timer to be disabled and unmasked and is compliant with | ||
206 | * the ARMv7 architecture. | ||
207 | */ | ||
208 | timer->cntv_ctl = 0; | ||
209 | |||
210 | /* | ||
203 | * Tell the VGIC that the virtual interrupt is tied to a | 211 | * Tell the VGIC that the virtual interrupt is tied to a |
204 | * physical interrupt. We do that once per VCPU. | 212 | * physical interrupt. We do that once per VCPU. |
205 | */ | 213 | */ |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 9eb489a2c94c..6bd1c9bf7ae7 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -1144,26 +1144,11 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq, | |||
1144 | struct irq_phys_map *map; | 1144 | struct irq_phys_map *map; |
1145 | map = vgic_irq_map_search(vcpu, irq); | 1145 | map = vgic_irq_map_search(vcpu, irq); |
1146 | 1146 | ||
1147 | /* | ||
1148 | * If we have a mapping, and the virtual interrupt is | ||
1149 | * being injected, then we must set the state to | ||
1150 | * active in the physical world. Otherwise the | ||
1151 | * physical interrupt will fire and the guest will | ||
1152 | * exit before processing the virtual interrupt. | ||
1153 | */ | ||
1154 | if (map) { | 1147 | if (map) { |
1155 | int ret; | ||
1156 | |||
1157 | BUG_ON(!map->active); | ||
1158 | vlr.hwirq = map->phys_irq; | 1148 | vlr.hwirq = map->phys_irq; |
1159 | vlr.state |= LR_HW; | 1149 | vlr.state |= LR_HW; |
1160 | vlr.state &= ~LR_EOI_INT; | 1150 | vlr.state &= ~LR_EOI_INT; |
1161 | 1151 | ||
1162 | ret = irq_set_irqchip_state(map->irq, | ||
1163 | IRQCHIP_STATE_ACTIVE, | ||
1164 | true); | ||
1165 | WARN_ON(ret); | ||
1166 | |||
1167 | /* | 1152 | /* |
1168 | * Make sure we're not going to sample this | 1153 | * Make sure we're not going to sample this |
1169 | * again, as a HW-backed interrupt cannot be | 1154 | * again, as a HW-backed interrupt cannot be |
@@ -1255,7 +1240,7 @@ static void __kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu) | |||
1255 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 1240 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
1256 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | 1241 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; |
1257 | unsigned long *pa_percpu, *pa_shared; | 1242 | unsigned long *pa_percpu, *pa_shared; |
1258 | int i, vcpu_id; | 1243 | int i, vcpu_id, lr, ret; |
1259 | int overflow = 0; | 1244 | int overflow = 0; |
1260 | int nr_shared = vgic_nr_shared_irqs(dist); | 1245 | int nr_shared = vgic_nr_shared_irqs(dist); |
1261 | 1246 | ||
@@ -1310,6 +1295,31 @@ epilog: | |||
1310 | */ | 1295 | */ |
1311 | clear_bit(vcpu_id, dist->irq_pending_on_cpu); | 1296 | clear_bit(vcpu_id, dist->irq_pending_on_cpu); |
1312 | } | 1297 | } |
1298 | |||
1299 | for (lr = 0; lr < vgic->nr_lr; lr++) { | ||
1300 | struct vgic_lr vlr; | ||
1301 | |||
1302 | if (!test_bit(lr, vgic_cpu->lr_used)) | ||
1303 | continue; | ||
1304 | |||
1305 | vlr = vgic_get_lr(vcpu, lr); | ||
1306 | |||
1307 | /* | ||
1308 | * If we have a mapping, and the virtual interrupt is | ||
1309 | * presented to the guest (as pending or active), then we must | ||
1310 | * set the state to active in the physical world. See | ||
1311 | * Documentation/virtual/kvm/arm/vgic-mapped-irqs.txt. | ||
1312 | */ | ||
1313 | if (vlr.state & LR_HW) { | ||
1314 | struct irq_phys_map *map; | ||
1315 | map = vgic_irq_map_search(vcpu, vlr.irq); | ||
1316 | |||
1317 | ret = irq_set_irqchip_state(map->irq, | ||
1318 | IRQCHIP_STATE_ACTIVE, | ||
1319 | true); | ||
1320 | WARN_ON(ret); | ||
1321 | } | ||
1322 | } | ||
1313 | } | 1323 | } |
1314 | 1324 | ||
1315 | static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | 1325 | static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) |