]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/amd64/vmm/io/vlapic_priv.h
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / amd64 / vmm / io / vlapic_priv.h
1 /*-
2  * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD$
27  */
28
29 #ifndef _VLAPIC_PRIV_H_
30 #define _VLAPIC_PRIV_H_
31
32 #include <x86/apicreg.h>
33
34 /*
35  * APIC Register:               Offset     Description
36  */
37 #define APIC_OFFSET_ID          0x20    /* Local APIC ID                */
38 #define APIC_OFFSET_VER         0x30    /* Local APIC Version           */
39 #define APIC_OFFSET_TPR         0x80    /* Task Priority Register       */
40 #define APIC_OFFSET_APR         0x90    /* Arbitration Priority         */
41 #define APIC_OFFSET_PPR         0xA0    /* Processor Priority Register  */
42 #define APIC_OFFSET_EOI         0xB0    /* EOI Register                 */
43 #define APIC_OFFSET_RRR         0xC0    /* Remote read                  */
44 #define APIC_OFFSET_LDR         0xD0    /* Logical Destination          */
45 #define APIC_OFFSET_DFR         0xE0    /* Destination Format Register  */
46 #define APIC_OFFSET_SVR         0xF0    /* Spurious Vector Register     */
47 #define APIC_OFFSET_ISR0        0x100   /* In Service Register          */
48 #define APIC_OFFSET_ISR1        0x110
49 #define APIC_OFFSET_ISR2        0x120
50 #define APIC_OFFSET_ISR3        0x130
51 #define APIC_OFFSET_ISR4        0x140
52 #define APIC_OFFSET_ISR5        0x150
53 #define APIC_OFFSET_ISR6        0x160
54 #define APIC_OFFSET_ISR7        0x170
55 #define APIC_OFFSET_TMR0        0x180   /* Trigger Mode Register        */
56 #define APIC_OFFSET_TMR1        0x190
57 #define APIC_OFFSET_TMR2        0x1A0
58 #define APIC_OFFSET_TMR3        0x1B0
59 #define APIC_OFFSET_TMR4        0x1C0
60 #define APIC_OFFSET_TMR5        0x1D0
61 #define APIC_OFFSET_TMR6        0x1E0
62 #define APIC_OFFSET_TMR7        0x1F0
63 #define APIC_OFFSET_IRR0        0x200   /* Interrupt Request Register   */
64 #define APIC_OFFSET_IRR1        0x210
65 #define APIC_OFFSET_IRR2        0x220
66 #define APIC_OFFSET_IRR3        0x230
67 #define APIC_OFFSET_IRR4        0x240
68 #define APIC_OFFSET_IRR5        0x250
69 #define APIC_OFFSET_IRR6        0x260
70 #define APIC_OFFSET_IRR7        0x270
71 #define APIC_OFFSET_ESR         0x280   /* Error Status Register        */
72 #define APIC_OFFSET_CMCI_LVT    0x2F0   /* Local Vector Table (CMCI)    */
73 #define APIC_OFFSET_ICR_LOW     0x300   /* Interrupt Command Register   */
74 #define APIC_OFFSET_ICR_HI      0x310
75 #define APIC_OFFSET_TIMER_LVT   0x320   /* Local Vector Table (Timer)   */
76 #define APIC_OFFSET_THERM_LVT   0x330   /* Local Vector Table (Thermal) */
77 #define APIC_OFFSET_PERF_LVT    0x340   /* Local Vector Table (PMC)     */
78 #define APIC_OFFSET_LINT0_LVT   0x350   /* Local Vector Table (LINT0)   */
79 #define APIC_OFFSET_LINT1_LVT   0x360   /* Local Vector Table (LINT1)   */
80 #define APIC_OFFSET_ERROR_LVT   0x370   /* Local Vector Table (ERROR)   */
81 #define APIC_OFFSET_TIMER_ICR   0x380   /* Timer's Initial Count        */
82 #define APIC_OFFSET_TIMER_CCR   0x390   /* Timer's Current Count        */
83 #define APIC_OFFSET_TIMER_DCR   0x3E0   /* Timer's Divide Configuration */
84 #define APIC_OFFSET_SELF_IPI    0x3F0   /* Self IPI register */
85
86 #define VLAPIC_CTR0(vlapic, format)                                     \
87         VCPU_CTR0((vlapic)->vm, (vlapic)->vcpuid, format)
88
89 #define VLAPIC_CTR1(vlapic, format, p1)                                 \
90         VCPU_CTR1((vlapic)->vm, (vlapic)->vcpuid, format, p1)
91
92 #define VLAPIC_CTR2(vlapic, format, p1, p2)                             \
93         VCPU_CTR2((vlapic)->vm, (vlapic)->vcpuid, format, p1, p2)
94
95 #define VLAPIC_CTR3(vlapic, format, p1, p2, p3)                         \
96         VCPU_CTR3((vlapic)->vm, (vlapic)->vcpuid, format, p1, p2, p3)
97
98 #define VLAPIC_CTR_IRR(vlapic, msg)                                     \
99 do {                                                                    \
100         uint32_t *irrptr = &(vlapic)->apic_page->irr0;                  \
101         irrptr[0] = irrptr[0];  /* silence compiler */                  \
102         VLAPIC_CTR1((vlapic), msg " irr0 0x%08x", irrptr[0 << 2]);      \
103         VLAPIC_CTR1((vlapic), msg " irr1 0x%08x", irrptr[1 << 2]);      \
104         VLAPIC_CTR1((vlapic), msg " irr2 0x%08x", irrptr[2 << 2]);      \
105         VLAPIC_CTR1((vlapic), msg " irr3 0x%08x", irrptr[3 << 2]);      \
106         VLAPIC_CTR1((vlapic), msg " irr4 0x%08x", irrptr[4 << 2]);      \
107         VLAPIC_CTR1((vlapic), msg " irr5 0x%08x", irrptr[5 << 2]);      \
108         VLAPIC_CTR1((vlapic), msg " irr6 0x%08x", irrptr[6 << 2]);      \
109         VLAPIC_CTR1((vlapic), msg " irr7 0x%08x", irrptr[7 << 2]);      \
110 } while (0)
111
112 #define VLAPIC_CTR_ISR(vlapic, msg)                                     \
113 do {                                                                    \
114         uint32_t *isrptr = &(vlapic)->apic_page->isr0;                  \
115         isrptr[0] = isrptr[0];  /* silence compiler */                  \
116         VLAPIC_CTR1((vlapic), msg " isr0 0x%08x", isrptr[0 << 2]);      \
117         VLAPIC_CTR1((vlapic), msg " isr1 0x%08x", isrptr[1 << 2]);      \
118         VLAPIC_CTR1((vlapic), msg " isr2 0x%08x", isrptr[2 << 2]);      \
119         VLAPIC_CTR1((vlapic), msg " isr3 0x%08x", isrptr[3 << 2]);      \
120         VLAPIC_CTR1((vlapic), msg " isr4 0x%08x", isrptr[4 << 2]);      \
121         VLAPIC_CTR1((vlapic), msg " isr5 0x%08x", isrptr[5 << 2]);      \
122         VLAPIC_CTR1((vlapic), msg " isr6 0x%08x", isrptr[6 << 2]);      \
123         VLAPIC_CTR1((vlapic), msg " isr7 0x%08x", isrptr[7 << 2]);      \
124 } while (0)
125
126 enum boot_state {
127         BS_INIT,
128         BS_SIPI,
129         BS_RUNNING
130 };
131
132 /*
133  * 16 priority levels with at most one vector injected per level.
134  */
135 #define ISRVEC_STK_SIZE         (16 + 1)
136
137 #define VLAPIC_MAXLVT_INDEX     APIC_LVT_CMCI
138
139 struct vlapic;
140
141 struct vlapic_ops {
142         int (*set_intr_ready)(struct vlapic *vlapic, int vector, bool level);
143         int (*pending_intr)(struct vlapic *vlapic, int *vecptr);
144         void (*intr_accepted)(struct vlapic *vlapic, int vector);
145         void (*post_intr)(struct vlapic *vlapic, int hostcpu);
146         void (*set_tmr)(struct vlapic *vlapic, int vector, bool level);
147         void (*enable_x2apic_mode)(struct vlapic *vlapic);
148 };
149
150 struct vlapic {
151         struct vm               *vm;
152         int                     vcpuid;
153         struct LAPIC            *apic_page;
154         struct vlapic_ops       ops;
155
156         uint32_t                esr_pending;
157         int                     esr_firing;
158
159         struct callout  callout;        /* vlapic timer */
160         struct bintime  timer_fire_bt;  /* callout expiry time */
161         struct bintime  timer_freq_bt;  /* timer frequency */
162         struct bintime  timer_period_bt; /* timer period */
163         struct mtx      timer_mtx;
164
165         /*
166          * The 'isrvec_stk' is a stack of vectors injected by the local apic.
167          * A vector is popped from the stack when the processor does an EOI.
168          * The vector on the top of the stack is used to compute the
169          * Processor Priority in conjunction with the TPR.
170          */
171         uint8_t         isrvec_stk[ISRVEC_STK_SIZE];
172         int             isrvec_stk_top;
173
174         uint64_t        msr_apicbase;
175         enum boot_state boot_state;
176
177         /*
178          * Copies of some registers in the virtual APIC page. We do this for
179          * a couple of different reasons:
180          * - to be able to detect what changed (e.g. svr_last)
181          * - to maintain a coherent snapshot of the register (e.g. lvt_last)
182          */
183         uint32_t        svr_last;
184         uint32_t        lvt_last[VLAPIC_MAXLVT_INDEX + 1];
185 };
186
187 void vlapic_init(struct vlapic *vlapic);
188 void vlapic_cleanup(struct vlapic *vlapic);
189
190 #endif  /* _VLAPIC_PRIV_H_ */