blob: 1e762138939f733bd9a80648a60d624c38831157 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
/*
* Copyright (C) 2015, 2016 ARM Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __ASM_ARM_NEW_VGIC_H
#define __ASM_ARM_NEW_VGIC_H
#include <asm/atomic.h>
#include <asm/mmio.h>
#include <xen/list.h>
#include <xen/mm.h>
#include <xen/spinlock.h>
#define VGIC_V3_MAX_CPUS 255
#define VGIC_V2_MAX_CPUS 8
#define VGIC_NR_SGIS 16
#define VGIC_NR_PPIS 16
#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)
#define VGIC_MAX_PRIVATE (VGIC_NR_PRIVATE_IRQS - 1)
#define VGIC_MAX_SPI 1019
#define VGIC_MAX_RESERVED 1023
#define VGIC_MIN_LPI 8192
#define irq_is_ppi(irq) ((irq) >= VGIC_NR_SGIS && (irq) < VGIC_NR_PRIVATE_IRQS)
#define irq_is_spi(irq) ((irq) >= VGIC_NR_PRIVATE_IRQS && \
(irq) <= VGIC_MAX_SPI)
enum vgic_type {
VGIC_V2, /* Good ol' GICv2 */
VGIC_V3, /* New fancy GICv3 */
};
#define VGIC_V2_MAX_LRS (1 << 6)
#define VGIC_V3_MAX_LRS 16
#define VGIC_V3_LR_INDEX(lr) (VGIC_V3_MAX_LRS - 1 - (lr))
#define VGIC_CONFIG_EDGE false
#define VGIC_CONFIG_LEVEL true
struct vgic_irq {
struct list_head ap_list;
struct vcpu *vcpu; /*
* SGIs and PPIs: The VCPU
* SPIs and LPIs: The VCPU whose ap_list
* this is queued on.
*/
struct vcpu *target_vcpu; /*
* The VCPU that this interrupt should
* be sent to, as a result of the
* targets reg (v2) or the affinity reg (v3).
*/
spinlock_t irq_lock; /* Protects the content of the struct */
uint32_t intid; /* Guest visible INTID */
atomic_t refcount; /* Used for LPIs */
uint32_t hwintid; /* HW INTID number */
union
{
struct {
uint8_t targets; /* GICv2 target VCPUs mask */
uint8_t source; /* GICv2 SGIs only */
};
uint32_t mpidr; /* GICv3 target VCPU */
};
uint8_t priority;
bool line_level:1; /* Level only */
bool pending_latch:1; /*
* The pending latch state used to
* calculate the pending state for both
* level and edge triggered IRQs.
*/
bool active:1; /* not used for LPIs */
bool enabled:1;
bool hw:1; /* Tied to HW IRQ */
bool config:1; /* Level or edge */
struct list_head lpi_list; /* Used to link all LPIs together */
};
enum iodev_type {
IODEV_DIST,
IODEV_REDIST,
};
struct vgic_io_device {
gfn_t base_fn;
struct vcpu *redist_vcpu;
const struct vgic_register_region *regions;
enum iodev_type iodev_type;
unsigned int nr_regions;
};
struct vgic_dist {
bool ready;
bool initialized;
/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
uint32_t version;
/* Do injected MSIs require an additional device ID? */
bool msis_require_devid;
unsigned int nr_spis;
/* base addresses in guest physical address space: */
paddr_t dbase; /* distributor */
union
{
/* either a GICv2 CPU interface */
paddr_t cbase;
/* or a number of GICv3 redistributor regions */
struct
{
paddr_t vgic_redist_base;
paddr_t vgic_redist_free_offset;
};
};
paddr_t csize; /* CPU interface size */
paddr_t vbase; /* virtual CPU interface base address */
/* distributor enabled */
bool enabled;
struct vgic_irq *spis;
unsigned long *allocated_irqs; /* bitmap of IRQs allocated */
struct vgic_io_device dist_iodev;
bool has_its;
/*
* Contains the attributes and gpa of the LPI configuration table.
* Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
* one address across all redistributors.
* GICv3 spec: 6.1.2 "LPI Configuration tables"
*/
uint64_t propbaser;
/* Protects the lpi_list and the count value below. */
spinlock_t lpi_list_lock;
struct list_head lpi_list_head;
unsigned int lpi_list_count;
};
struct vgic_cpu {
struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
struct list_head ap_list_head;
spinlock_t ap_list_lock; /* Protects the ap_list */
unsigned int used_lrs;
/*
* List of IRQs that this VCPU should consider because they are either
* Active or Pending (hence the name; AP list), or because they recently
* were one of the two and need to be migrated off this list to another
* VCPU.
*/
/*
* Members below are used with GICv3 emulation only and represent
* parts of the redistributor.
*/
struct vgic_io_device rd_iodev;
struct vgic_io_device sgi_iodev;
/* Contains the attributes and gpa of the LPI pending tables. */
uint64_t pendbaser;
bool lpis_enabled;
/* Cache guest priority bits */
uint32_t num_pri_bits;
/* Cache guest interrupt ID bits */
uint32_t num_id_bits;
};
static inline paddr_t vgic_cpu_base(const struct vgic_dist *vgic)
{
return vgic->cbase;
}
static inline paddr_t vgic_dist_base(const struct vgic_dist *vgic)
{
return vgic->dbase;
}
#endif /* __ASM_ARM_NEW_VGIC_H */
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* indent-tabs-mode: nil
* End:
*/
|