diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2013-06-04 05:29:39 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2014-07-11 07:57:31 -0400 |
commit | 69bb2c9fbc11d9d4358fbb798db15c9092eb4d8c (patch) | |
tree | ca465df2f2ae90a961d315652aa6028a20bdabcb /virt | |
parent | 8d5c6b06a5d5f8ebcf40558e566781d572920740 (diff) |
KVM: ARM: vgic: abstract access to the ELRSR bitmap
Move the GICH_ELRSR access to its own functions, and add them to
the vgic_ops structure.
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/vgic.c | 46 |
1 files changed, 41 insertions, 5 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 11408fee600e..6dcc974fa2b4 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -1015,9 +1015,32 @@ static void vgic_v2_set_lr(struct kvm_vcpu *vcpu, int lr, | |||
1015 | vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; | 1015 | vcpu->arch.vgic_cpu.vgic_v2.vgic_lr[lr] = lr_val; |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, | ||
1019 | struct vgic_lr lr_desc) | ||
1020 | { | ||
1021 | if (!(lr_desc.state & LR_STATE_MASK)) | ||
1022 | set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr); | ||
1023 | } | ||
1024 | |||
1025 | static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu) | ||
1026 | { | ||
1027 | u64 val; | ||
1028 | |||
1029 | #if BITS_PER_LONG == 64 | ||
1030 | val = vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[1]; | ||
1031 | val <<= 32; | ||
1032 | val |= vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr[0]; | ||
1033 | #else | ||
1034 | val = *(u64 *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr; | ||
1035 | #endif | ||
1036 | return val; | ||
1037 | } | ||
1038 | |||
1018 | static const struct vgic_ops vgic_ops = { | 1039 | static const struct vgic_ops vgic_ops = { |
1019 | .get_lr = vgic_v2_get_lr, | 1040 | .get_lr = vgic_v2_get_lr, |
1020 | .set_lr = vgic_v2_set_lr, | 1041 | .set_lr = vgic_v2_set_lr, |
1042 | .sync_lr_elrsr = vgic_v2_sync_lr_elrsr, | ||
1043 | .get_elrsr = vgic_v2_get_elrsr, | ||
1021 | }; | 1044 | }; |
1022 | 1045 | ||
1023 | static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr) | 1046 | static struct vgic_lr vgic_get_lr(const struct kvm_vcpu *vcpu, int lr) |
@@ -1031,6 +1054,17 @@ static void vgic_set_lr(struct kvm_vcpu *vcpu, int lr, | |||
1031 | vgic_ops.set_lr(vcpu, lr, vlr); | 1054 | vgic_ops.set_lr(vcpu, lr, vlr); |
1032 | } | 1055 | } |
1033 | 1056 | ||
1057 | static void vgic_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, | ||
1058 | struct vgic_lr vlr) | ||
1059 | { | ||
1060 | vgic_ops.sync_lr_elrsr(vcpu, lr, vlr); | ||
1061 | } | ||
1062 | |||
1063 | static inline u64 vgic_get_elrsr(struct kvm_vcpu *vcpu) | ||
1064 | { | ||
1065 | return vgic_ops.get_elrsr(vcpu); | ||
1066 | } | ||
1067 | |||
1034 | static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu) | 1068 | static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu) |
1035 | { | 1069 | { |
1036 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 1070 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
@@ -1260,7 +1294,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | |||
1260 | * Despite being EOIed, the LR may not have | 1294 | * Despite being EOIed, the LR may not have |
1261 | * been marked as empty. | 1295 | * been marked as empty. |
1262 | */ | 1296 | */ |
1263 | set_bit(lr, (unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr); | 1297 | vgic_sync_lr_elrsr(vcpu, lr, vlr); |
1264 | } | 1298 | } |
1265 | } | 1299 | } |
1266 | 1300 | ||
@@ -1278,14 +1312,17 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) | |||
1278 | { | 1312 | { |
1279 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 1313 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
1280 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | 1314 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; |
1315 | u64 elrsr; | ||
1316 | unsigned long *elrsr_ptr; | ||
1281 | int lr, pending; | 1317 | int lr, pending; |
1282 | bool level_pending; | 1318 | bool level_pending; |
1283 | 1319 | ||
1284 | level_pending = vgic_process_maintenance(vcpu); | 1320 | level_pending = vgic_process_maintenance(vcpu); |
1321 | elrsr = vgic_get_elrsr(vcpu); | ||
1322 | elrsr_ptr = (unsigned long *)&elrsr; | ||
1285 | 1323 | ||
1286 | /* Clear mappings for empty LRs */ | 1324 | /* Clear mappings for empty LRs */ |
1287 | for_each_set_bit(lr, (unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr, | 1325 | for_each_set_bit(lr, elrsr_ptr, vgic_cpu->nr_lr) { |
1288 | vgic_cpu->nr_lr) { | ||
1289 | struct vgic_lr vlr; | 1326 | struct vgic_lr vlr; |
1290 | 1327 | ||
1291 | if (!test_and_clear_bit(lr, vgic_cpu->lr_used)) | 1328 | if (!test_and_clear_bit(lr, vgic_cpu->lr_used)) |
@@ -1298,8 +1335,7 @@ static void __kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu) | |||
1298 | } | 1335 | } |
1299 | 1336 | ||
1300 | /* Check if we still have something up our sleeve... */ | 1337 | /* Check if we still have something up our sleeve... */ |
1301 | pending = find_first_zero_bit((unsigned long *)vgic_cpu->vgic_v2.vgic_elrsr, | 1338 | pending = find_first_zero_bit(elrsr_ptr, vgic_cpu->nr_lr); |
1302 | vgic_cpu->nr_lr); | ||
1303 | if (level_pending || pending < vgic_cpu->nr_lr) | 1339 | if (level_pending || pending < vgic_cpu->nr_lr) |
1304 | set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu); | 1340 | set_bit(vcpu->vcpu_id, &dist->irq_pending_on_cpu); |
1305 | } | 1341 | } |