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