4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
25 #ifndef __SYS_APIX_APIX_H
26 #define __SYS_APIX_APIX_H
29 #include <sys/avintr.h>
30 #include <sys/traptrace.h>
32 #include <sys/apic_common.h>
33 #include <sys/apic_timer.h>
45 #define APIX_NAME "apix"
47 #define APIX_NVECTOR 256 /* max number of per-cpu vectors */
48 #define APIX_NIRQ 256 /* maximum number of IRQs */
49 #define APIX_INVALID_VECT 0 /* invalid vector */
52 #define APIX_TYPE_FIXED DDI_INTR_TYPE_FIXED /* 1 */
53 #define APIX_TYPE_MSI DDI_INTR_TYPE_MSI /* 2 */
54 #define APIX_TYPE_MSIX DDI_INTR_TYPE_MSIX /* 4 */
55 #define APIX_TYPE_IPI 8
60 APIX_STATE_OBSOLETED
, /* 1 */
61 APIX_STATE_ALLOCED
, /* 2 */
62 APIX_STATE_ENABLED
, /* 3 */
63 APIX_STATE_DISABLED
/* 4 */
65 #define IS_VECT_FREE(p) \
66 (((p) == NULL) || ((p)->v_state == APIX_STATE_FREED))
67 #define IS_VECT_OBSOL(p) \
68 (((p) != NULL) && ((p)->v_state == APIX_STATE_OBSOLETED))
69 #define IS_VECT_ENABLED(p) \
70 (((p) != NULL) && ((p)->v_state == APIX_STATE_ENABLED))
73 #define APIX_VECT_USER_BOUND 0x1
74 #define APIX_VECT_MASKABLE 0x2
77 * Number of interrupt vectors reserved by software on each LOCAL APIC:
84 #define APIX_SW_RESERVED_VECTORS 5
87 * Macros to help deal with shared interrupts and to differentiate
88 * between vector and irq number when passing arguments to interfaces
91 #define APIX_VIRTVEC_VECMASK 0xff
92 #define APIX_VIRTVEC_FLAG 0x80000000
93 #define APIX_VIRTVECTOR(cpuid, v) \
94 (APIX_VIRTVEC_FLAG | ((cpuid) << 8) | (v))
95 #define APIX_IS_VIRTVEC(vv) \
96 ((vv) & APIX_VIRTVEC_FLAG)
97 #define APIX_VIRTVEC_VECTOR(vv) \
98 (((uchar_t)(vv)) & APIX_VIRTVEC_VECMASK)
99 #define APIX_VIRTVEC_CPU(vv) \
100 (((uint32_t)(vv) & ~APIX_VIRTVEC_FLAG) >> 8)
102 struct apix_dev_vector
;
103 typedef struct apix_vector
{
105 ushort_t v_type
; /* interrupt type */
106 processorid_t v_cpuid
; /* current target cpu */
107 uchar_t v_vector
; /* vector */
108 uchar_t v_share
; /* intrs at this vector */
109 int v_inum
; /* irq for fixed, inum for msi/x */
111 processorid_t v_bound_cpuid
; /* binding cpu */
112 uint_t v_busy
; /* How frequently did clock */
113 /* find us in this */
114 uint_t v_pri
; /* maximum priority */
115 struct autovec
*v_autovect
; /* ISR linked list */
116 void *v_intrmap_private
; /* intr remap data */
117 struct apix_dev_vector
*v_devp
; /* pointer to device */
118 struct apix_vector
*v_next
; /* next on per-cpu obosoletes chain */
121 typedef struct apix_impl
{
122 processorid_t x_cpuid
; /* cpu number */
124 uint16_t x_intr_pending
; /* pending intr by IPL */
125 /* pointer to head of interrupt pending list */
126 struct autovec
*x_intr_head
[PIL_MAX
+ 1];
127 /* pointer to tail of interrupt pending list */
128 struct autovec
*x_intr_tail
[PIL_MAX
+ 1];
130 apix_vector_t
*x_obsoletes
; /* obosoleted vectors */
131 apix_vector_t
*x_vectbl
[APIX_NVECTOR
]; /* vector table */
136 #define HILEVEL_PENDING(cpu) \
137 (apixs[(cpu)->cpu_id]->x_intr_pending & CPU_INTR_ACTV_HIGH_LEVEL_MASK)
138 #define LOWLEVEL_PENDING(cpu) \
139 (apixs[(cpu)->cpu_id]->x_intr_pending & ~CPU_INTR_ACTV_HIGH_LEVEL_MASK)
140 #define IS_HILEVEL_RUNNING(cpu) \
141 (((ushort_t)((cpu)->intr_actv)) & CPU_INTR_ACTV_HIGH_LEVEL_MASK)
142 #define IS_LOWLEVEL_RUNNING(cpu) \
143 (((ushort_t)((cpu)->intr_actv)) & ~CPU_INTR_ACTV_HIGH_LEVEL_MASK)
145 #define INTR_PENDING(apixp, ipl) \
146 ((ipl) <= LOCK_LEVEL ? \
147 ((apixp)->x_intr_pending & (1 << (ipl))) : \
148 ((apixp)->x_intr_pending >> (LOCK_LEVEL + 1)))
151 * We need a way to find allocated vector for a device. One option
152 * is to maintain a mapping table in pcplusmp. Another option would
153 * be to record vector or irq with interrupt handler hdlp->ih_vector or
155 * Second option requires interface changes, such as, a new interface
156 * for noticing vector changes caused by interrupt re-targeting.
157 * Currently we choose the first option cause it doesn't require
160 typedef struct apix_dev_vector
{
162 int dv_inum
; /* interrupt number */
163 int dv_type
; /* interrupt type */
164 apix_vector_t
*dv_vector
; /* vector */
165 struct apix_dev_vector
*dv_next
; /* per major chain */
168 extern lock_t apix_lock
;
169 extern apix_impl_t
*apixs
[];
170 extern int apix_nipis
;
171 extern int apix_cpu_nvectors
;
172 extern apix_dev_vector_t
**apix_dev_vector
;
173 extern processorid_t
*apix_major_to_cpu
;
174 extern kmutex_t apix_mutex
;
176 #define xv_vector(cpu, v) apixs[(cpu)]->x_vectbl[(v)]
177 #define xv_intrmap_private(cpu, v) (xv_vector(cpu, v))->v_intrmap_private
179 #define APIX_IPI_MAX APIC_MAX_VECTOR
180 #define APIX_IPI_MIN (APIX_NVECTOR - apix_nipis)
181 #define APIX_AVINTR_MIN 0x20
182 #define APIX_NAVINTR \
183 (apix_cpu_nvectors - apix_nipis - APIX_AVINTR_MIN)
184 #define APIX_AVINTR_MAX \
185 ((APIX_NAVINTR <= 0) ? 0 : \
186 (((APIX_AVINTR_MIN + APIX_NAVINTR) > APIX_IPI_MIN) ? \
187 (APIX_IPI_MIN - 2) : \
188 (APIX_AVINTR_MIN + APIX_NAVINTR - 2)))
189 #define APIX_RESV_VECTOR (APIX_AVINTR_MAX + 1)
191 #define IS_VALID_AVINTR(v) \
192 ((v) >= APIX_AVINTR_MIN && (v) <= APIX_AVINTR_MAX)
194 #define APIX_ENTER_CPU_LOCK(cpuid) lock_set(&apixs[(cpuid)]->x_lock)
195 #define APIX_LEAVE_CPU_LOCK(cpuid) lock_clear(&apixs[(cpuid)]->x_lock)
196 #define APIX_CPU_LOCK_HELD(cpuid) LOCK_HELD(&apixs[(cpuid)]->x_lock)
198 /* Get dip for msi/x */
199 #define APIX_GET_DIP(v) \
200 ((v)->v_devp->dv_dip)
205 extern apic_irq_t
*apic_irq_table
[APIC_MAX_VECTOR
+1];
206 #define IS_IRQ_FREE(p) \
207 ((p) == NULL || ((p)->airq_mps_intr_index == FREE_INDEX))
209 #define UNREFERENCED_1PARAMETER(_p) _NOTE(ARGUNUSED(_p))
210 #define UNREFERENCED_3PARAMETER(_p, _q, _r) _NOTE(ARGUNUSED(_p, _q, _r))
213 * From mp_platform_common.c
215 extern int apic_intr_policy
;
216 extern iflag_t apic_sci_flags
;
217 extern int apic_hpet_vect
;
218 extern iflag_t apic_hpet_flags
;
219 extern int apic_redist_cpu_skip
;
220 extern int apic_num_imbalance
;
221 extern int apic_num_rebind
;
222 extern struct apic_io_intr
*apic_io_intrp
;
223 extern int apic_use_acpi_madt_only
;
224 extern uint32_t eisa_level_intr_mask
;
225 extern int apic_pci_bus_total
;
226 extern uchar_t apic_single_pci_busid
;
228 extern ACPI_MADT_INTERRUPT_OVERRIDE
*acpi_isop
;
229 extern int acpi_iso_cnt
;
231 extern int apic_defconf
;
232 extern int apic_irq_translate
;
234 extern int apic_max_reps_clear_pending
;
236 extern int apic_probe_common(char *modname
);
237 extern uchar_t
acpi_find_ioapic(int irq
);
238 extern int apic_find_bus_id(int bustype
);
239 extern int apic_find_intin(uchar_t ioapic
, uchar_t intin
);
240 extern struct apic_io_intr
*apic_find_io_intr_w_busid(int irqno
, int busid
);
241 extern int apic_acpi_translate_pci_irq(dev_info_t
*dip
, int busid
, int devid
,
242 int ipin
, int *pci_irqp
, iflag_t
*intr_flagp
);
243 extern int apic_handle_pci_pci_bridge(dev_info_t
*idip
, int child_devno
,
244 int child_ipin
, struct apic_io_intr
**intrp
);
245 extern void apic_record_rdt_entry(apic_irq_t
*irqptr
, int irq
);
250 extern int apic_have_32bit_cr8
;
255 extern void apix_do_interrupt(struct regs
*rp
, trap_trace_rec_t
*ttp
);
261 typedef struct apix_rebind_info
{
262 int i_go
; /* if rebinding op is in progress */
264 processorid_t i_old_cpuid
;
265 struct autovec
*i_old_av
;
266 processorid_t i_new_cpuid
;
267 struct autovec
*i_new_av
;
268 } apix_rebind_info_t
;
270 extern struct apix_rebind_info apix_rebindinfo
;
272 #define APIX_SET_REBIND_INFO(_ovp, _nvp)\
273 if (((_ovp)->v_flags & APIX_VECT_MASKABLE) == 0) {\
274 apix_rebindinfo.i_pri = (_ovp)->v_pri;\
275 apix_rebindinfo.i_old_cpuid = (_ovp)->v_cpuid;\
276 apix_rebindinfo.i_old_av = (_ovp)->v_autovect;\
277 apix_rebindinfo.i_new_cpuid = (_nvp)->v_cpuid;\
278 apix_rebindinfo.i_new_av = (_nvp)->v_autovect;\
279 apix_rebindinfo.i_go = 1;\
282 #define APIX_CLR_REBIND_INFO() \
283 apix_rebindinfo.i_go = 0
285 #define APIX_IS_FAKE_INTR(_vector)\
286 (apix_rebindinfo.i_go && (_vector) == APIX_RESV_VECTOR)
288 #define APIX_DO_FAKE_INTR(_cpu, _vector)\
289 if (APIX_IS_FAKE_INTR(_vector)) {\
291 if ((_cpu) == apix_rebindinfo.i_old_cpuid)\
292 tp = apix_rebindinfo.i_old_av;\
293 else if ((_cpu) == apix_rebindinfo.i_new_cpuid)\
294 tp = apix_rebindinfo.i_new_av;\
295 if (tp->av_vector != NULL &&\
296 (tp->av_flags & AV_PENTRY_PEND) == 0) {\
297 tp->av_flags |= AV_PENTRY_PEND;\
298 apix_insert_pending_av(apixs[(_cpu)], tp,\
300 apixs[(_cpu)]->x_intr_pending |=\
301 (1 << tp->av_prilevel);\
305 extern int apix_add_avintr(void *intr_id
, int ipl
, avfunc xxintr
, char *name
,
306 int vector
, caddr_t arg1
, caddr_t arg2
, uint64_t *ticksp
, dev_info_t
*dip
);
307 extern void apix_rem_avintr(void *intr_id
, int ipl
, avfunc xxintr
,
310 extern uint32_t apix_bind_cpu_locked(dev_info_t
*dip
);
311 extern apix_vector_t
*apix_rebind(apix_vector_t
*vecp
, processorid_t tocpu
,
314 extern uchar_t
apix_alloc_ipi(int ipl
);
315 extern apix_vector_t
*apix_alloc_intx(dev_info_t
*dip
, int inum
, int irqno
);
316 extern int apix_alloc_msi(dev_info_t
*dip
, int inum
, int count
, int behavior
);
317 extern int apix_alloc_msix(dev_info_t
*dip
, int inum
, int count
, int behavior
);
318 extern void apix_free_vectors(dev_info_t
*dip
, int inum
, int count
, int type
);
319 extern void apix_enable_vector(apix_vector_t
*vecp
);
320 extern void apix_disable_vector(apix_vector_t
*vecp
);
321 extern int apix_obsolete_vector(apix_vector_t
*vecp
);
322 extern int apix_find_cont_vector_oncpu(uint32_t cpuid
, int count
);
324 extern void apix_set_dev_map(apix_vector_t
*vecp
, dev_info_t
*dip
, int inum
);
325 extern apix_vector_t
*apix_get_dev_map(dev_info_t
*dip
, int inum
, int type
);
326 extern apix_vector_t
*apix_setup_io_intr(apix_vector_t
*vecp
);
327 extern void ioapix_init_intr(int mask_apic
);
328 extern int apix_get_min_dev_inum(dev_info_t
*dip
, int type
);
329 extern int apix_get_max_dev_inum(dev_info_t
*dip
, int type
);
334 extern int apix_addspl(int virtvec
, int ipl
, int min_ipl
, int max_ipl
);
335 extern int apix_delspl(int virtvec
, int ipl
, int min_ipl
, int max_ipl
);
336 extern void apix_intx_set_vector(int irqno
, uint32_t cpuid
, uchar_t vector
);
337 extern apix_vector_t
*apix_intx_get_vector(int irqno
);
338 extern void apix_intx_enable(int irqno
);
339 extern void apix_intx_disable(int irqno
);
340 extern void apix_intx_free(int irqno
);
341 extern int apix_intx_rebind(int irqno
, processorid_t cpuid
, uchar_t vector
);
342 extern apix_vector_t
*apix_set_cpu(apix_vector_t
*vecp
, int new_cpu
,
344 extern apix_vector_t
*apix_grp_set_cpu(apix_vector_t
*vecp
, int new_cpu
,
346 extern void apix_level_intr_pre_eoi(int irq
);
347 extern void apix_level_intr_post_dispatch(int irq
);
353 #endif /* __SYS_APIX_APIX_H */