Block secondary ITS instances from attaching on ARM64
[freebsd.git] / sys / arm64 / arm64 / gic_v3_var.h
1 /*-
2  * Copyright (c) 2015 The FreeBSD Foundation
3  * All rights reserved.
4  *
5  * This software was developed by Semihalf under
6  * the sponsorship of the FreeBSD Foundation.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * $FreeBSD$
30  */
31
32 #ifndef _GIC_V3_VAR_H_
33 #define _GIC_V3_VAR_H_
34
35 #define GIC_V3_DEVSTR   "ARM Generic Interrupt Controller v3.0"
36
37 DECLARE_CLASS(gic_v3_driver);
38
39 #define LPI_FLAGS_CONF_FLUSH    (1UL << 0)
40 #define LPI_CONFTAB_SIZE        PAGE_SIZE_64K
41 /* 1 bit per LPI + 1 KB more for the obligatory PPI, SGI, SPI stuff */
42 #define LPI_PENDTAB_SIZE        ((LPI_CONFTAB_SIZE / 8) + 0x400)
43
44 struct redist_lpis {
45         vm_offset_t             conf_base;
46         vm_offset_t             pend_base[MAXCPU];
47         uint64_t                flags;
48 };
49
50 struct gic_redists {
51         /*
52          * Re-Distributor region description.
53          * We will have few of those depending
54          * on the #redistributor-regions property in FDT.
55          */
56         struct resource **      regions;
57         /* Number of Re-Distributor regions */
58         u_int                   nregions;
59         /* Per-CPU Re-Distributor handler */
60         struct resource *       pcpu[MAXCPU];
61         /* LPIs data */
62         struct redist_lpis      lpis;
63 };
64
65 struct gic_v3_softc {
66         device_t                dev;
67         struct resource **      gic_res;
68         struct mtx              gic_mtx;
69         /* Distributor */
70         struct resource *       gic_dist;
71         /* Re-Distributors */
72         struct gic_redists      gic_redists;
73
74         u_int                   gic_nirqs;
75         u_int                   gic_idbits;
76
77         boolean_t               gic_registered;
78 };
79
80 MALLOC_DECLARE(M_GIC_V3);
81
82 /* Device methods */
83 int gic_v3_attach(device_t dev);
84 int gic_v3_detach(device_t dev);
85
86 /*
87  * ITS
88  */
89 #define GIC_V3_ITS_DEVSTR       "ARM GIC Interrupt Translation Service"
90 #define GIC_V3_ITS_COMPSTR      "arm,gic-v3-its"
91
92 DECLARE_CLASS(gic_v3_its_driver);
93
94 /* LPI chunk owned by ITS device */
95 struct lpi_chunk {
96         u_int   lpi_base;
97         u_int   lpi_num;
98         u_int   lpi_free;       /* First free LPI in set */
99 };
100
101 /* ITS device */
102 struct its_dev {
103         TAILQ_ENTRY(its_dev)    entry;
104         /* PCI device */
105         device_t                pci_dev;
106         /* Device ID (i.e. PCI device ID) */
107         uint32_t                devid;
108         /* List of assigned LPIs */
109         struct lpi_chunk        lpis;
110         /* Virtual address of ITT */
111         vm_offset_t             itt;
112         /* Interrupt collection */
113         struct its_col *        col;
114 };
115 TAILQ_HEAD(its_dev_list, its_dev);
116
117 /* ITS private table description */
118 struct its_ptab {
119         vm_offset_t     ptab_vaddr;     /* Virtual Address of table */
120         size_t          ptab_pgsz;      /* Page size */
121         size_t          ptab_npages;    /* Number of pages */
122 };
123
124 /* ITS collection description. */
125 struct its_col {
126         uint64_t        col_target;     /* Target Re-Distributor */
127         uint64_t        col_id;         /* Collection ID */
128 };
129
130 /* ITS command. Each command is 32 bytes long */
131 struct its_cmd {
132         uint64_t        cmd_dword[4];   /* ITS command double word */
133 };
134
135 /* ITS commands encoding */
136 #define ITS_CMD_SYNC            (0x05)
137 #define ITS_CMD_MAPD            (0x08)
138 #define ITS_CMD_MAPC            (0x09)
139 #define ITS_CMD_MAPVI           (0x0a)
140 #define ITS_CMD_MAPI            (0x0b)
141 #define ITS_CMD_INV             (0x0c)
142 #define ITS_CMD_INVALL          (0x0d)
143 /* Command */
144 #define CMD_COMMAND_MASK        (0xFFUL)
145 /* PCI device ID */
146 #define CMD_DEVID_SHIFT         (32)
147 #define CMD_DEVID_MASK          (0xFFFFFFFFUL << CMD_DEVID_SHIFT)
148 /* Size of IRQ ID bitfield */
149 #define CMD_SIZE_MASK           (0xFFUL)
150 /* Virtual LPI ID */
151 #define CMD_ID_MASK             (0xFFFFFFFFUL)
152 /* Physical LPI ID */
153 #define CMD_PID_SHIFT           (32)
154 #define CMD_PID_MASK            (0xFFFFFFFFUL << CMD_PID_SHIFT)
155 /* Collection */
156 #define CMD_COL_MASK            (0xFFFFUL)
157 /* Target (CPU or Re-Distributor) */
158 #define CMD_TARGET_SHIFT        (16)
159 #define CMD_TARGET_MASK         (0xFFFFFFFFUL << CMD_TARGET_SHIFT)
160 /* Interrupt Translation Table address */
161 #define CMD_ITT_MASK            (0xFFFFFFFFFF00UL)
162 /* Valid command bit */
163 #define CMD_VALID_SHIFT         (63)
164 #define CMD_VALID_MASK          (1UL << CMD_VALID_SHIFT)
165
166 /*
167  * ITS command descriptor.
168  * Idea for command description passing taken from Linux.
169  */
170 struct its_cmd_desc {
171         uint8_t cmd_type;
172
173         union {
174                 struct {
175                         struct its_col *col;
176                 } cmd_desc_sync;
177
178                 struct {
179                         struct its_col *col;
180                         uint8_t valid;
181                 } cmd_desc_mapc;
182
183                 struct {
184                         struct its_dev *its_dev;
185                         uint32_t pid;
186                         uint32_t id;
187                 } cmd_desc_mapvi;
188
189                 struct {
190                         struct its_dev *its_dev;
191                         uint32_t lpinum;
192                 } cmd_desc_mapi;
193
194                 struct {
195                         struct its_dev *its_dev;
196                         uint8_t valid;
197                 } cmd_desc_mapd;
198
199                 struct {
200                         struct its_dev *its_dev;
201                         uint32_t lpinum;
202                 } cmd_desc_inv;
203
204                 struct {
205                         struct its_col *col;
206                 } cmd_desc_invall;
207         };
208 };
209
210 #define ITS_CMDQ_SIZE           PAGE_SIZE_64K
211 #define ITS_CMDQ_NENTRIES       (ITS_CMDQ_SIZE / sizeof(struct its_cmd))
212
213 #define ITS_FLAGS_CMDQ_FLUSH    (1UL << 0)
214
215 #define ITS_TARGET_NONE         0xFBADBEEF
216
217 struct gic_v3_its_softc {
218         device_t                dev;
219         struct resource *       its_res;
220
221         struct its_cmd *        its_cmdq_base;  /* ITS command queue base */
222         struct its_cmd *        its_cmdq_write; /* ITS command queue write ptr */
223         struct its_ptab         its_ptabs[GITS_BASER_NUM];/* ITS private tables */
224         struct its_col *        its_cols[MAXCPU];/* Per-CPU collections */
225
226         uint64_t                its_flags;
227
228         struct its_dev_list     its_dev_list;
229
230         unsigned long *         its_lpi_bitmap;
231         uint32_t                its_lpi_maxid;
232
233         struct mtx              its_mtx;
234         struct mtx              its_spin_mtx;
235
236         uint32_t                its_socket;     /* Socket number ITS is attached to */
237 };
238
239 /* Stuff that is specific to the vendor's implementation */
240 typedef uint32_t (*its_devbits_func_t)(device_t);
241 typedef uint32_t (*its_devid_func_t)(device_t);
242
243 struct its_quirks {
244         uint64_t                cpuid;
245         uint64_t                cpuid_mask;
246         its_devid_func_t        devid_func;
247         its_devbits_func_t      devbits_func;
248 };
249
250 extern devclass_t gic_v3_its_devclass;
251
252 int gic_v3_its_detach(device_t);
253
254 int gic_v3_its_alloc_msix(device_t, device_t, int *);
255 int gic_v3_its_alloc_msi(device_t, device_t, int, int *);
256 int gic_v3_its_map_msix(device_t, device_t, int, uint64_t *, uint32_t *);
257
258 int its_init_cpu(struct gic_v3_its_softc *);
259
260 void lpi_unmask_irq(device_t, uint32_t);
261 void lpi_mask_irq(device_t, uint32_t);
262 /*
263  * GIC Distributor accessors.
264  * Notice that only GIC sofc can be passed.
265  */
266 #define gic_d_read(sc, len, reg)                \
267 ({                                              \
268         bus_read_##len(sc->gic_dist, reg);      \
269 })
270
271 #define gic_d_write(sc, len, reg, val)          \
272 ({                                              \
273         bus_write_##len(sc->gic_dist, reg, val);\
274 })
275
276 /* GIC Re-Distributor accessors (per-CPU) */
277 #define gic_r_read(sc, len, reg)                \
278 ({                                              \
279         u_int cpu = PCPU_GET(cpuid);            \
280                                                 \
281         bus_read_##len(                         \
282             sc->gic_redists.pcpu[cpu],          \
283             reg);                               \
284 })
285
286 #define gic_r_write(sc, len, reg, val)          \
287 ({                                              \
288         u_int cpu = PCPU_GET(cpuid);            \
289                                                 \
290         bus_write_##len(                        \
291             sc->gic_redists.pcpu[cpu],          \
292             reg, val);                          \
293 })
294
295 #define PCI_DEVID_GENERIC(pci_dev)                              \
296 ({                                                              \
297         ((pci_get_domain(pci_dev) << PCI_RID_DOMAIN_SHIFT) |    \
298         (pci_get_bus(pci_dev) << PCI_RID_BUS_SHIFT) |           \
299         (pci_get_slot(pci_dev) << PCI_RID_SLOT_SHIFT) |         \
300         (pci_get_function(pci_dev) << PCI_RID_FUNC_SHIFT));     \
301 })
302
303 /*
304  * Request number of maximum MSI-X vectors for this device.
305  * Device can ask for less vectors than maximum supported but not more.
306  */
307 #define PCI_MSIX_NUM(pci_dev)                   \
308 ({                                              \
309         struct pci_devinfo *dinfo;              \
310         pcicfgregs *cfg;                        \
311                                                 \
312         dinfo = device_get_ivars(pci_dev);      \
313         cfg = &dinfo->cfg;                      \
314                                                 \
315         cfg->msix.msix_msgnum;                  \
316 })
317
318 #endif /* _GIC_V3_VAR_H_ */