Commit | Line | Data |
---|---|---|
83215812 AP |
1 | /* |
2 | * Copyright (C) 2012-2014 ARM Ltd. | |
3 | * Author: Marc Zyngier <marc.zyngier@arm.com> | |
4 | * | |
5 | * Derived from virt/kvm/arm/vgic.c | |
6 | * | |
7 | * This program is free software; you can redistribute it and/or modify | |
8 | * it under the terms of the GNU General Public License version 2 as | |
9 | * published by the Free Software Foundation. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
18 | */ | |
19 | ||
20 | #ifndef __KVM_VGIC_H__ | |
21 | #define __KVM_VGIC_H__ | |
22 | ||
6777f77f AP |
23 | #include <kvm/iodev.h> |
24 | ||
83215812 AP |
25 | #define VGIC_ADDR_UNDEF (-1) |
26 | #define IS_VGIC_ADDR_UNDEF(_x) ((_x) == VGIC_ADDR_UNDEF) | |
27 | ||
28 | #define PRODUCT_ID_KVM 0x4b /* ASCII code K */ | |
29 | #define IMPLEMENTER_ARM 0x43b | |
30 | ||
31 | #define ACCESS_READ_VALUE (1 << 0) | |
32 | #define ACCESS_READ_RAZ (0 << 0) | |
33 | #define ACCESS_READ_MASK(x) ((x) & (1 << 0)) | |
34 | #define ACCESS_WRITE_IGNORED (0 << 1) | |
35 | #define ACCESS_WRITE_SETBIT (1 << 1) | |
36 | #define ACCESS_WRITE_CLEARBIT (2 << 1) | |
37 | #define ACCESS_WRITE_VALUE (3 << 1) | |
38 | #define ACCESS_WRITE_MASK(x) ((x) & (3 << 1)) | |
39 | ||
a0675c25 AP |
40 | #define VCPU_NOT_ALLOCATED ((u8)-1) |
41 | ||
83215812 AP |
42 | unsigned long *vgic_bitmap_get_shared_map(struct vgic_bitmap *x); |
43 | ||
44 | void vgic_update_state(struct kvm *kvm); | |
45 | int vgic_init_common_maps(struct kvm *kvm); | |
46 | ||
47 | u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, int cpuid, u32 offset); | |
48 | u32 *vgic_bytemap_get_reg(struct vgic_bytemap *x, int cpuid, u32 offset); | |
49 | ||
50 | void vgic_dist_irq_set_pending(struct kvm_vcpu *vcpu, int irq); | |
51 | void vgic_dist_irq_clear_pending(struct kvm_vcpu *vcpu, int irq); | |
52 | void vgic_cpu_irq_clear(struct kvm_vcpu *vcpu, int irq); | |
53 | void vgic_bitmap_set_irq_val(struct vgic_bitmap *x, int cpuid, | |
54 | int irq, int val); | |
55 | ||
56 | void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); | |
57 | void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr); | |
58 | ||
59 | bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq); | |
60 | void vgic_unqueue_irqs(struct kvm_vcpu *vcpu); | |
61 | ||
950324ab AP |
62 | struct kvm_exit_mmio { |
63 | phys_addr_t phys_addr; | |
64 | void *data; | |
65 | u32 len; | |
66 | bool is_write; | |
67 | void *private; | |
68 | }; | |
69 | ||
83215812 AP |
70 | void vgic_reg_access(struct kvm_exit_mmio *mmio, u32 *reg, |
71 | phys_addr_t offset, int mode); | |
72 | bool handle_mmio_raz_wi(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, | |
73 | phys_addr_t offset); | |
74 | ||
75 | static inline | |
76 | u32 mmio_data_read(struct kvm_exit_mmio *mmio, u32 mask) | |
77 | { | |
78 | return le32_to_cpu(*((u32 *)mmio->data)) & mask; | |
79 | } | |
80 | ||
81 | static inline | |
82 | void mmio_data_write(struct kvm_exit_mmio *mmio, u32 mask, u32 value) | |
83 | { | |
84 | *((u32 *)mmio->data) = cpu_to_le32(value) & mask; | |
85 | } | |
86 | ||
cf50a1eb | 87 | struct vgic_io_range { |
83215812 AP |
88 | phys_addr_t base; |
89 | unsigned long len; | |
90 | int bits_per_irq; | |
91 | bool (*handle_mmio)(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, | |
92 | phys_addr_t offset); | |
93 | }; | |
94 | ||
6777f77f AP |
95 | int vgic_register_kvm_io_dev(struct kvm *kvm, gpa_t base, int len, |
96 | const struct vgic_io_range *ranges, | |
97 | int redist_id, | |
98 | struct vgic_io_device *iodev); | |
99 | ||
83215812 AP |
100 | static inline bool is_in_range(phys_addr_t addr, unsigned long len, |
101 | phys_addr_t baseaddr, unsigned long size) | |
102 | { | |
103 | return (addr >= baseaddr) && (addr + len <= baseaddr + size); | |
104 | } | |
105 | ||
106 | const | |
cf50a1eb | 107 | struct vgic_io_range *vgic_find_range(const struct vgic_io_range *ranges, |
9f199d0a | 108 | int len, gpa_t offset); |
83215812 | 109 | |
83215812 AP |
110 | bool vgic_handle_enable_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio, |
111 | phys_addr_t offset, int vcpu_id, int access); | |
112 | ||
113 | bool vgic_handle_set_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio, | |
114 | phys_addr_t offset, int vcpu_id); | |
115 | ||
116 | bool vgic_handle_clear_pending_reg(struct kvm *kvm, struct kvm_exit_mmio *mmio, | |
117 | phys_addr_t offset, int vcpu_id); | |
118 | ||
47a98b15 CD |
119 | bool vgic_handle_set_active_reg(struct kvm *kvm, |
120 | struct kvm_exit_mmio *mmio, | |
121 | phys_addr_t offset, int vcpu_id); | |
122 | ||
123 | bool vgic_handle_clear_active_reg(struct kvm *kvm, | |
124 | struct kvm_exit_mmio *mmio, | |
125 | phys_addr_t offset, int vcpu_id); | |
126 | ||
83215812 AP |
127 | bool vgic_handle_cfg_reg(u32 *reg, struct kvm_exit_mmio *mmio, |
128 | phys_addr_t offset); | |
129 | ||
130 | void vgic_kick_vcpus(struct kvm *kvm); | |
131 | ||
cf50a1eb | 132 | int vgic_has_attr_regs(const struct vgic_io_range *ranges, phys_addr_t offset); |
83215812 AP |
133 | int vgic_set_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr); |
134 | int vgic_get_common_attr(struct kvm_device *dev, struct kvm_device_attr *attr); | |
135 | ||
136 | int vgic_init(struct kvm *kvm); | |
137 | void vgic_v2_init_emulation(struct kvm *kvm); | |
a0675c25 | 138 | void vgic_v3_init_emulation(struct kvm *kvm); |
83215812 AP |
139 | |
140 | #endif |