1*3a9fd824SRoger Pau Monné /*
2*3a9fd824SRoger Pau Monné * Structure definitions for HVM state that is held by Xen and must
3*3a9fd824SRoger Pau Monné * be saved along with the domain's memory and device-model state.
4*3a9fd824SRoger Pau Monné *
5*3a9fd824SRoger Pau Monné * Copyright (c) 2007 XenSource Ltd.
6*3a9fd824SRoger Pau Monné *
7*3a9fd824SRoger Pau Monné * Permission is hereby granted, free of charge, to any person obtaining a copy
8*3a9fd824SRoger Pau Monné * of this software and associated documentation files (the "Software"), to
9*3a9fd824SRoger Pau Monné * deal in the Software without restriction, including without limitation the
10*3a9fd824SRoger Pau Monné * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11*3a9fd824SRoger Pau Monné * sell copies of the Software, and to permit persons to whom the Software is
12*3a9fd824SRoger Pau Monné * furnished to do so, subject to the following conditions:
13*3a9fd824SRoger Pau Monné *
14*3a9fd824SRoger Pau Monné * The above copyright notice and this permission notice shall be included in
15*3a9fd824SRoger Pau Monné * all copies or substantial portions of the Software.
16*3a9fd824SRoger Pau Monné *
17*3a9fd824SRoger Pau Monné * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18*3a9fd824SRoger Pau Monné * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19*3a9fd824SRoger Pau Monné * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20*3a9fd824SRoger Pau Monné * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21*3a9fd824SRoger Pau Monné * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22*3a9fd824SRoger Pau Monné * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23*3a9fd824SRoger Pau Monné * DEALINGS IN THE SOFTWARE.
24*3a9fd824SRoger Pau Monné */
25*3a9fd824SRoger Pau Monné
26*3a9fd824SRoger Pau Monné #ifndef __XEN_PUBLIC_HVM_SAVE_X86_H__
27*3a9fd824SRoger Pau Monné #define __XEN_PUBLIC_HVM_SAVE_X86_H__
28*3a9fd824SRoger Pau Monné
29*3a9fd824SRoger Pau Monné #include "../../xen.h"
30*3a9fd824SRoger Pau Monné
31*3a9fd824SRoger Pau Monné /*
32*3a9fd824SRoger Pau Monné * Save/restore header: general info about the save file.
33*3a9fd824SRoger Pau Monné */
34*3a9fd824SRoger Pau Monné
35*3a9fd824SRoger Pau Monné #define HVM_FILE_MAGIC 0x54381286
36*3a9fd824SRoger Pau Monné #define HVM_FILE_VERSION 0x00000001
37*3a9fd824SRoger Pau Monné
38*3a9fd824SRoger Pau Monné struct hvm_save_header {
39*3a9fd824SRoger Pau Monné uint32_t magic; /* Must be HVM_FILE_MAGIC */
40*3a9fd824SRoger Pau Monné uint32_t version; /* File format version */
41*3a9fd824SRoger Pau Monné uint64_t changeset; /* Version of Xen that saved this file */
42*3a9fd824SRoger Pau Monné uint32_t cpuid; /* CPUID[0x01][%eax] on the saving machine */
43*3a9fd824SRoger Pau Monné uint32_t gtsc_khz; /* Guest's TSC frequency in kHz */
44*3a9fd824SRoger Pau Monné };
45*3a9fd824SRoger Pau Monné
46*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
47*3a9fd824SRoger Pau Monné
48*3a9fd824SRoger Pau Monné
49*3a9fd824SRoger Pau Monné /*
50*3a9fd824SRoger Pau Monné * Processor
51*3a9fd824SRoger Pau Monné *
52*3a9fd824SRoger Pau Monné * Compat:
53*3a9fd824SRoger Pau Monné * - Pre-3.4 didn't have msr_tsc_aux
54*3a9fd824SRoger Pau Monné * - Pre-4.7 didn't have fpu_initialised
55*3a9fd824SRoger Pau Monné */
56*3a9fd824SRoger Pau Monné
57*3a9fd824SRoger Pau Monné struct hvm_hw_cpu {
58*3a9fd824SRoger Pau Monné uint8_t fpu_regs[512];
59*3a9fd824SRoger Pau Monné
60*3a9fd824SRoger Pau Monné uint64_t rax;
61*3a9fd824SRoger Pau Monné uint64_t rbx;
62*3a9fd824SRoger Pau Monné uint64_t rcx;
63*3a9fd824SRoger Pau Monné uint64_t rdx;
64*3a9fd824SRoger Pau Monné uint64_t rbp;
65*3a9fd824SRoger Pau Monné uint64_t rsi;
66*3a9fd824SRoger Pau Monné uint64_t rdi;
67*3a9fd824SRoger Pau Monné uint64_t rsp;
68*3a9fd824SRoger Pau Monné uint64_t r8;
69*3a9fd824SRoger Pau Monné uint64_t r9;
70*3a9fd824SRoger Pau Monné uint64_t r10;
71*3a9fd824SRoger Pau Monné uint64_t r11;
72*3a9fd824SRoger Pau Monné uint64_t r12;
73*3a9fd824SRoger Pau Monné uint64_t r13;
74*3a9fd824SRoger Pau Monné uint64_t r14;
75*3a9fd824SRoger Pau Monné uint64_t r15;
76*3a9fd824SRoger Pau Monné
77*3a9fd824SRoger Pau Monné uint64_t rip;
78*3a9fd824SRoger Pau Monné uint64_t rflags;
79*3a9fd824SRoger Pau Monné
80*3a9fd824SRoger Pau Monné uint64_t cr0;
81*3a9fd824SRoger Pau Monné uint64_t cr2;
82*3a9fd824SRoger Pau Monné uint64_t cr3;
83*3a9fd824SRoger Pau Monné uint64_t cr4;
84*3a9fd824SRoger Pau Monné
85*3a9fd824SRoger Pau Monné uint64_t dr0;
86*3a9fd824SRoger Pau Monné uint64_t dr1;
87*3a9fd824SRoger Pau Monné uint64_t dr2;
88*3a9fd824SRoger Pau Monné uint64_t dr3;
89*3a9fd824SRoger Pau Monné uint64_t dr6;
90*3a9fd824SRoger Pau Monné uint64_t dr7;
91*3a9fd824SRoger Pau Monné
92*3a9fd824SRoger Pau Monné uint32_t cs_sel;
93*3a9fd824SRoger Pau Monné uint32_t ds_sel;
94*3a9fd824SRoger Pau Monné uint32_t es_sel;
95*3a9fd824SRoger Pau Monné uint32_t fs_sel;
96*3a9fd824SRoger Pau Monné uint32_t gs_sel;
97*3a9fd824SRoger Pau Monné uint32_t ss_sel;
98*3a9fd824SRoger Pau Monné uint32_t tr_sel;
99*3a9fd824SRoger Pau Monné uint32_t ldtr_sel;
100*3a9fd824SRoger Pau Monné
101*3a9fd824SRoger Pau Monné uint32_t cs_limit;
102*3a9fd824SRoger Pau Monné uint32_t ds_limit;
103*3a9fd824SRoger Pau Monné uint32_t es_limit;
104*3a9fd824SRoger Pau Monné uint32_t fs_limit;
105*3a9fd824SRoger Pau Monné uint32_t gs_limit;
106*3a9fd824SRoger Pau Monné uint32_t ss_limit;
107*3a9fd824SRoger Pau Monné uint32_t tr_limit;
108*3a9fd824SRoger Pau Monné uint32_t ldtr_limit;
109*3a9fd824SRoger Pau Monné uint32_t idtr_limit;
110*3a9fd824SRoger Pau Monné uint32_t gdtr_limit;
111*3a9fd824SRoger Pau Monné
112*3a9fd824SRoger Pau Monné uint64_t cs_base;
113*3a9fd824SRoger Pau Monné uint64_t ds_base;
114*3a9fd824SRoger Pau Monné uint64_t es_base;
115*3a9fd824SRoger Pau Monné uint64_t fs_base;
116*3a9fd824SRoger Pau Monné uint64_t gs_base;
117*3a9fd824SRoger Pau Monné uint64_t ss_base;
118*3a9fd824SRoger Pau Monné uint64_t tr_base;
119*3a9fd824SRoger Pau Monné uint64_t ldtr_base;
120*3a9fd824SRoger Pau Monné uint64_t idtr_base;
121*3a9fd824SRoger Pau Monné uint64_t gdtr_base;
122*3a9fd824SRoger Pau Monné
123*3a9fd824SRoger Pau Monné uint32_t cs_arbytes;
124*3a9fd824SRoger Pau Monné uint32_t ds_arbytes;
125*3a9fd824SRoger Pau Monné uint32_t es_arbytes;
126*3a9fd824SRoger Pau Monné uint32_t fs_arbytes;
127*3a9fd824SRoger Pau Monné uint32_t gs_arbytes;
128*3a9fd824SRoger Pau Monné uint32_t ss_arbytes;
129*3a9fd824SRoger Pau Monné uint32_t tr_arbytes;
130*3a9fd824SRoger Pau Monné uint32_t ldtr_arbytes;
131*3a9fd824SRoger Pau Monné
132*3a9fd824SRoger Pau Monné uint64_t sysenter_cs;
133*3a9fd824SRoger Pau Monné uint64_t sysenter_esp;
134*3a9fd824SRoger Pau Monné uint64_t sysenter_eip;
135*3a9fd824SRoger Pau Monné
136*3a9fd824SRoger Pau Monné /* msr for em64t */
137*3a9fd824SRoger Pau Monné uint64_t shadow_gs;
138*3a9fd824SRoger Pau Monné
139*3a9fd824SRoger Pau Monné /* msr content saved/restored. */
140*3a9fd824SRoger Pau Monné uint64_t msr_flags; /* Obsolete, ignored. */
141*3a9fd824SRoger Pau Monné uint64_t msr_lstar;
142*3a9fd824SRoger Pau Monné uint64_t msr_star;
143*3a9fd824SRoger Pau Monné uint64_t msr_cstar;
144*3a9fd824SRoger Pau Monné uint64_t msr_syscall_mask;
145*3a9fd824SRoger Pau Monné uint64_t msr_efer;
146*3a9fd824SRoger Pau Monné uint64_t msr_tsc_aux;
147*3a9fd824SRoger Pau Monné
148*3a9fd824SRoger Pau Monné /* guest's idea of what rdtsc() would return */
149*3a9fd824SRoger Pau Monné uint64_t tsc;
150*3a9fd824SRoger Pau Monné
151*3a9fd824SRoger Pau Monné /* pending event, if any */
152*3a9fd824SRoger Pau Monné union {
153*3a9fd824SRoger Pau Monné uint32_t pending_event;
154*3a9fd824SRoger Pau Monné struct {
155*3a9fd824SRoger Pau Monné uint8_t pending_vector:8;
156*3a9fd824SRoger Pau Monné uint8_t pending_type:3;
157*3a9fd824SRoger Pau Monné uint8_t pending_error_valid:1;
158*3a9fd824SRoger Pau Monné uint32_t pending_reserved:19;
159*3a9fd824SRoger Pau Monné uint8_t pending_valid:1;
160*3a9fd824SRoger Pau Monné };
161*3a9fd824SRoger Pau Monné };
162*3a9fd824SRoger Pau Monné /* error code for pending event */
163*3a9fd824SRoger Pau Monné uint32_t error_code;
164*3a9fd824SRoger Pau Monné
165*3a9fd824SRoger Pau Monné #define _XEN_X86_FPU_INITIALISED 0
166*3a9fd824SRoger Pau Monné #define XEN_X86_FPU_INITIALISED (1U<<_XEN_X86_FPU_INITIALISED)
167*3a9fd824SRoger Pau Monné uint32_t flags;
168*3a9fd824SRoger Pau Monné uint32_t pad0;
169*3a9fd824SRoger Pau Monné };
170*3a9fd824SRoger Pau Monné
171*3a9fd824SRoger Pau Monné struct hvm_hw_cpu_compat {
172*3a9fd824SRoger Pau Monné uint8_t fpu_regs[512];
173*3a9fd824SRoger Pau Monné
174*3a9fd824SRoger Pau Monné uint64_t rax;
175*3a9fd824SRoger Pau Monné uint64_t rbx;
176*3a9fd824SRoger Pau Monné uint64_t rcx;
177*3a9fd824SRoger Pau Monné uint64_t rdx;
178*3a9fd824SRoger Pau Monné uint64_t rbp;
179*3a9fd824SRoger Pau Monné uint64_t rsi;
180*3a9fd824SRoger Pau Monné uint64_t rdi;
181*3a9fd824SRoger Pau Monné uint64_t rsp;
182*3a9fd824SRoger Pau Monné uint64_t r8;
183*3a9fd824SRoger Pau Monné uint64_t r9;
184*3a9fd824SRoger Pau Monné uint64_t r10;
185*3a9fd824SRoger Pau Monné uint64_t r11;
186*3a9fd824SRoger Pau Monné uint64_t r12;
187*3a9fd824SRoger Pau Monné uint64_t r13;
188*3a9fd824SRoger Pau Monné uint64_t r14;
189*3a9fd824SRoger Pau Monné uint64_t r15;
190*3a9fd824SRoger Pau Monné
191*3a9fd824SRoger Pau Monné uint64_t rip;
192*3a9fd824SRoger Pau Monné uint64_t rflags;
193*3a9fd824SRoger Pau Monné
194*3a9fd824SRoger Pau Monné uint64_t cr0;
195*3a9fd824SRoger Pau Monné uint64_t cr2;
196*3a9fd824SRoger Pau Monné uint64_t cr3;
197*3a9fd824SRoger Pau Monné uint64_t cr4;
198*3a9fd824SRoger Pau Monné
199*3a9fd824SRoger Pau Monné uint64_t dr0;
200*3a9fd824SRoger Pau Monné uint64_t dr1;
201*3a9fd824SRoger Pau Monné uint64_t dr2;
202*3a9fd824SRoger Pau Monné uint64_t dr3;
203*3a9fd824SRoger Pau Monné uint64_t dr6;
204*3a9fd824SRoger Pau Monné uint64_t dr7;
205*3a9fd824SRoger Pau Monné
206*3a9fd824SRoger Pau Monné uint32_t cs_sel;
207*3a9fd824SRoger Pau Monné uint32_t ds_sel;
208*3a9fd824SRoger Pau Monné uint32_t es_sel;
209*3a9fd824SRoger Pau Monné uint32_t fs_sel;
210*3a9fd824SRoger Pau Monné uint32_t gs_sel;
211*3a9fd824SRoger Pau Monné uint32_t ss_sel;
212*3a9fd824SRoger Pau Monné uint32_t tr_sel;
213*3a9fd824SRoger Pau Monné uint32_t ldtr_sel;
214*3a9fd824SRoger Pau Monné
215*3a9fd824SRoger Pau Monné uint32_t cs_limit;
216*3a9fd824SRoger Pau Monné uint32_t ds_limit;
217*3a9fd824SRoger Pau Monné uint32_t es_limit;
218*3a9fd824SRoger Pau Monné uint32_t fs_limit;
219*3a9fd824SRoger Pau Monné uint32_t gs_limit;
220*3a9fd824SRoger Pau Monné uint32_t ss_limit;
221*3a9fd824SRoger Pau Monné uint32_t tr_limit;
222*3a9fd824SRoger Pau Monné uint32_t ldtr_limit;
223*3a9fd824SRoger Pau Monné uint32_t idtr_limit;
224*3a9fd824SRoger Pau Monné uint32_t gdtr_limit;
225*3a9fd824SRoger Pau Monné
226*3a9fd824SRoger Pau Monné uint64_t cs_base;
227*3a9fd824SRoger Pau Monné uint64_t ds_base;
228*3a9fd824SRoger Pau Monné uint64_t es_base;
229*3a9fd824SRoger Pau Monné uint64_t fs_base;
230*3a9fd824SRoger Pau Monné uint64_t gs_base;
231*3a9fd824SRoger Pau Monné uint64_t ss_base;
232*3a9fd824SRoger Pau Monné uint64_t tr_base;
233*3a9fd824SRoger Pau Monné uint64_t ldtr_base;
234*3a9fd824SRoger Pau Monné uint64_t idtr_base;
235*3a9fd824SRoger Pau Monné uint64_t gdtr_base;
236*3a9fd824SRoger Pau Monné
237*3a9fd824SRoger Pau Monné uint32_t cs_arbytes;
238*3a9fd824SRoger Pau Monné uint32_t ds_arbytes;
239*3a9fd824SRoger Pau Monné uint32_t es_arbytes;
240*3a9fd824SRoger Pau Monné uint32_t fs_arbytes;
241*3a9fd824SRoger Pau Monné uint32_t gs_arbytes;
242*3a9fd824SRoger Pau Monné uint32_t ss_arbytes;
243*3a9fd824SRoger Pau Monné uint32_t tr_arbytes;
244*3a9fd824SRoger Pau Monné uint32_t ldtr_arbytes;
245*3a9fd824SRoger Pau Monné
246*3a9fd824SRoger Pau Monné uint64_t sysenter_cs;
247*3a9fd824SRoger Pau Monné uint64_t sysenter_esp;
248*3a9fd824SRoger Pau Monné uint64_t sysenter_eip;
249*3a9fd824SRoger Pau Monné
250*3a9fd824SRoger Pau Monné /* msr for em64t */
251*3a9fd824SRoger Pau Monné uint64_t shadow_gs;
252*3a9fd824SRoger Pau Monné
253*3a9fd824SRoger Pau Monné /* msr content saved/restored. */
254*3a9fd824SRoger Pau Monné uint64_t msr_flags; /* Obsolete, ignored. */
255*3a9fd824SRoger Pau Monné uint64_t msr_lstar;
256*3a9fd824SRoger Pau Monné uint64_t msr_star;
257*3a9fd824SRoger Pau Monné uint64_t msr_cstar;
258*3a9fd824SRoger Pau Monné uint64_t msr_syscall_mask;
259*3a9fd824SRoger Pau Monné uint64_t msr_efer;
260*3a9fd824SRoger Pau Monné /*uint64_t msr_tsc_aux; COMPAT */
261*3a9fd824SRoger Pau Monné
262*3a9fd824SRoger Pau Monné /* guest's idea of what rdtsc() would return */
263*3a9fd824SRoger Pau Monné uint64_t tsc;
264*3a9fd824SRoger Pau Monné
265*3a9fd824SRoger Pau Monné /* pending event, if any */
266*3a9fd824SRoger Pau Monné union {
267*3a9fd824SRoger Pau Monné uint32_t pending_event;
268*3a9fd824SRoger Pau Monné struct {
269*3a9fd824SRoger Pau Monné uint8_t pending_vector:8;
270*3a9fd824SRoger Pau Monné uint8_t pending_type:3;
271*3a9fd824SRoger Pau Monné uint8_t pending_error_valid:1;
272*3a9fd824SRoger Pau Monné uint32_t pending_reserved:19;
273*3a9fd824SRoger Pau Monné uint8_t pending_valid:1;
274*3a9fd824SRoger Pau Monné };
275*3a9fd824SRoger Pau Monné };
276*3a9fd824SRoger Pau Monné /* error code for pending event */
277*3a9fd824SRoger Pau Monné uint32_t error_code;
278*3a9fd824SRoger Pau Monné };
279*3a9fd824SRoger Pau Monné
_hvm_hw_fix_cpu(void * h,uint32_t size)280*3a9fd824SRoger Pau Monné static inline int _hvm_hw_fix_cpu(void *h, uint32_t size) {
281*3a9fd824SRoger Pau Monné
282*3a9fd824SRoger Pau Monné union hvm_hw_cpu_union {
283*3a9fd824SRoger Pau Monné struct hvm_hw_cpu nat;
284*3a9fd824SRoger Pau Monné struct hvm_hw_cpu_compat cmp;
285*3a9fd824SRoger Pau Monné } *ucpu = (union hvm_hw_cpu_union *)h;
286*3a9fd824SRoger Pau Monné
287*3a9fd824SRoger Pau Monné if ( size == sizeof(struct hvm_hw_cpu_compat) )
288*3a9fd824SRoger Pau Monné {
289*3a9fd824SRoger Pau Monné /*
290*3a9fd824SRoger Pau Monné * If we copy from the end backwards, we should
291*3a9fd824SRoger Pau Monné * be able to do the modification in-place.
292*3a9fd824SRoger Pau Monné */
293*3a9fd824SRoger Pau Monné ucpu->nat.error_code = ucpu->cmp.error_code;
294*3a9fd824SRoger Pau Monné ucpu->nat.pending_event = ucpu->cmp.pending_event;
295*3a9fd824SRoger Pau Monné ucpu->nat.tsc = ucpu->cmp.tsc;
296*3a9fd824SRoger Pau Monné ucpu->nat.msr_tsc_aux = 0;
297*3a9fd824SRoger Pau Monné }
298*3a9fd824SRoger Pau Monné /* Mimic the old behaviour by unconditionally setting fpu_initialised. */
299*3a9fd824SRoger Pau Monné ucpu->nat.flags = XEN_X86_FPU_INITIALISED;
300*3a9fd824SRoger Pau Monné
301*3a9fd824SRoger Pau Monné return 0;
302*3a9fd824SRoger Pau Monné }
303*3a9fd824SRoger Pau Monné
304*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE_COMPAT(CPU, 2, struct hvm_hw_cpu, \
305*3a9fd824SRoger Pau Monné struct hvm_hw_cpu_compat, _hvm_hw_fix_cpu);
306*3a9fd824SRoger Pau Monné
307*3a9fd824SRoger Pau Monné /*
308*3a9fd824SRoger Pau Monné * PIC
309*3a9fd824SRoger Pau Monné */
310*3a9fd824SRoger Pau Monné
311*3a9fd824SRoger Pau Monné struct hvm_hw_vpic {
312*3a9fd824SRoger Pau Monné /* IR line bitmasks. */
313*3a9fd824SRoger Pau Monné uint8_t irr;
314*3a9fd824SRoger Pau Monné uint8_t imr;
315*3a9fd824SRoger Pau Monné uint8_t isr;
316*3a9fd824SRoger Pau Monné
317*3a9fd824SRoger Pau Monné /* Line IRx maps to IRQ irq_base+x */
318*3a9fd824SRoger Pau Monné uint8_t irq_base;
319*3a9fd824SRoger Pau Monné
320*3a9fd824SRoger Pau Monné /*
321*3a9fd824SRoger Pau Monné * Where are we in ICW2-4 initialisation (0 means no init in progress)?
322*3a9fd824SRoger Pau Monné * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
323*3a9fd824SRoger Pau Monné * Bit 2: ICW1.IC4 (1 == ICW4 included in init sequence)
324*3a9fd824SRoger Pau Monné * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
325*3a9fd824SRoger Pau Monné */
326*3a9fd824SRoger Pau Monné uint8_t init_state:4;
327*3a9fd824SRoger Pau Monné
328*3a9fd824SRoger Pau Monné /* IR line with highest priority. */
329*3a9fd824SRoger Pau Monné uint8_t priority_add:4;
330*3a9fd824SRoger Pau Monné
331*3a9fd824SRoger Pau Monné /* Reads from A=0 obtain ISR or IRR? */
332*3a9fd824SRoger Pau Monné uint8_t readsel_isr:1;
333*3a9fd824SRoger Pau Monné
334*3a9fd824SRoger Pau Monné /* Reads perform a polling read? */
335*3a9fd824SRoger Pau Monné uint8_t poll:1;
336*3a9fd824SRoger Pau Monné
337*3a9fd824SRoger Pau Monné /* Automatically clear IRQs from the ISR during INTA? */
338*3a9fd824SRoger Pau Monné uint8_t auto_eoi:1;
339*3a9fd824SRoger Pau Monné
340*3a9fd824SRoger Pau Monné /* Automatically rotate IRQ priorities during AEOI? */
341*3a9fd824SRoger Pau Monné uint8_t rotate_on_auto_eoi:1;
342*3a9fd824SRoger Pau Monné
343*3a9fd824SRoger Pau Monné /* Exclude slave inputs when considering in-service IRQs? */
344*3a9fd824SRoger Pau Monné uint8_t special_fully_nested_mode:1;
345*3a9fd824SRoger Pau Monné
346*3a9fd824SRoger Pau Monné /* Special mask mode excludes masked IRs from AEOI and priority checks. */
347*3a9fd824SRoger Pau Monné uint8_t special_mask_mode:1;
348*3a9fd824SRoger Pau Monné
349*3a9fd824SRoger Pau Monné /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
350*3a9fd824SRoger Pau Monné uint8_t is_master:1;
351*3a9fd824SRoger Pau Monné
352*3a9fd824SRoger Pau Monné /* Edge/trigger selection. */
353*3a9fd824SRoger Pau Monné uint8_t elcr;
354*3a9fd824SRoger Pau Monné
355*3a9fd824SRoger Pau Monné /* Virtual INT output. */
356*3a9fd824SRoger Pau Monné uint8_t int_output;
357*3a9fd824SRoger Pau Monné };
358*3a9fd824SRoger Pau Monné
359*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
360*3a9fd824SRoger Pau Monné
361*3a9fd824SRoger Pau Monné
362*3a9fd824SRoger Pau Monné /*
363*3a9fd824SRoger Pau Monné * IO-APIC
364*3a9fd824SRoger Pau Monné */
365*3a9fd824SRoger Pau Monné
366*3a9fd824SRoger Pau Monné union vioapic_redir_entry
367*3a9fd824SRoger Pau Monné {
368*3a9fd824SRoger Pau Monné uint64_t bits;
369*3a9fd824SRoger Pau Monné struct {
370*3a9fd824SRoger Pau Monné uint8_t vector;
371*3a9fd824SRoger Pau Monné uint8_t delivery_mode:3;
372*3a9fd824SRoger Pau Monné uint8_t dest_mode:1;
373*3a9fd824SRoger Pau Monné uint8_t delivery_status:1;
374*3a9fd824SRoger Pau Monné uint8_t polarity:1;
375*3a9fd824SRoger Pau Monné uint8_t remote_irr:1;
376*3a9fd824SRoger Pau Monné uint8_t trig_mode:1;
377*3a9fd824SRoger Pau Monné uint8_t mask:1;
378*3a9fd824SRoger Pau Monné uint8_t reserve:7;
379*3a9fd824SRoger Pau Monné uint8_t reserved[4];
380*3a9fd824SRoger Pau Monné uint8_t dest_id;
381*3a9fd824SRoger Pau Monné } fields;
382*3a9fd824SRoger Pau Monné };
383*3a9fd824SRoger Pau Monné
384*3a9fd824SRoger Pau Monné #define VIOAPIC_NUM_PINS 48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
385*3a9fd824SRoger Pau Monné
386*3a9fd824SRoger Pau Monné #define XEN_HVM_VIOAPIC(name, cnt) \
387*3a9fd824SRoger Pau Monné struct name { \
388*3a9fd824SRoger Pau Monné uint64_t base_address; \
389*3a9fd824SRoger Pau Monné uint32_t ioregsel; \
390*3a9fd824SRoger Pau Monné uint32_t id; \
391*3a9fd824SRoger Pau Monné union vioapic_redir_entry redirtbl[cnt]; \
392*3a9fd824SRoger Pau Monné }
393*3a9fd824SRoger Pau Monné
394*3a9fd824SRoger Pau Monné XEN_HVM_VIOAPIC(hvm_hw_vioapic, VIOAPIC_NUM_PINS);
395*3a9fd824SRoger Pau Monné
396*3a9fd824SRoger Pau Monné #ifndef __XEN__
397*3a9fd824SRoger Pau Monné #undef XEN_HVM_VIOAPIC
398*3a9fd824SRoger Pau Monné #else
399*3a9fd824SRoger Pau Monné #undef VIOAPIC_NUM_PINS
400*3a9fd824SRoger Pau Monné #endif
401*3a9fd824SRoger Pau Monné
402*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
403*3a9fd824SRoger Pau Monné
404*3a9fd824SRoger Pau Monné
405*3a9fd824SRoger Pau Monné /*
406*3a9fd824SRoger Pau Monné * LAPIC
407*3a9fd824SRoger Pau Monné */
408*3a9fd824SRoger Pau Monné
409*3a9fd824SRoger Pau Monné struct hvm_hw_lapic {
410*3a9fd824SRoger Pau Monné uint64_t apic_base_msr;
411*3a9fd824SRoger Pau Monné uint32_t disabled; /* VLAPIC_xx_DISABLED */
412*3a9fd824SRoger Pau Monné uint32_t timer_divisor;
413*3a9fd824SRoger Pau Monné uint64_t tdt_msr;
414*3a9fd824SRoger Pau Monné };
415*3a9fd824SRoger Pau Monné
416*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
417*3a9fd824SRoger Pau Monné
418*3a9fd824SRoger Pau Monné struct hvm_hw_lapic_regs {
419*3a9fd824SRoger Pau Monné uint8_t data[1024];
420*3a9fd824SRoger Pau Monné };
421*3a9fd824SRoger Pau Monné
422*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
423*3a9fd824SRoger Pau Monné
424*3a9fd824SRoger Pau Monné
425*3a9fd824SRoger Pau Monné /*
426*3a9fd824SRoger Pau Monné * IRQs
427*3a9fd824SRoger Pau Monné */
428*3a9fd824SRoger Pau Monné
429*3a9fd824SRoger Pau Monné struct hvm_hw_pci_irqs {
430*3a9fd824SRoger Pau Monné /*
431*3a9fd824SRoger Pau Monné * Virtual interrupt wires for a single PCI bus.
432*3a9fd824SRoger Pau Monné * Indexed by: device*4 + INTx#.
433*3a9fd824SRoger Pau Monné */
434*3a9fd824SRoger Pau Monné union {
435*3a9fd824SRoger Pau Monné unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
436*3a9fd824SRoger Pau Monné uint64_t pad[2];
437*3a9fd824SRoger Pau Monné };
438*3a9fd824SRoger Pau Monné };
439*3a9fd824SRoger Pau Monné
440*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
441*3a9fd824SRoger Pau Monné
442*3a9fd824SRoger Pau Monné struct hvm_hw_isa_irqs {
443*3a9fd824SRoger Pau Monné /*
444*3a9fd824SRoger Pau Monné * Virtual interrupt wires for ISA devices.
445*3a9fd824SRoger Pau Monné * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
446*3a9fd824SRoger Pau Monné */
447*3a9fd824SRoger Pau Monné union {
448*3a9fd824SRoger Pau Monné unsigned long i[1]; /* DECLARE_BITMAP(i, 16); */
449*3a9fd824SRoger Pau Monné uint64_t pad[1];
450*3a9fd824SRoger Pau Monné };
451*3a9fd824SRoger Pau Monné };
452*3a9fd824SRoger Pau Monné
453*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
454*3a9fd824SRoger Pau Monné
455*3a9fd824SRoger Pau Monné struct hvm_hw_pci_link {
456*3a9fd824SRoger Pau Monné /*
457*3a9fd824SRoger Pau Monné * PCI-ISA interrupt router.
458*3a9fd824SRoger Pau Monné * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
459*3a9fd824SRoger Pau Monné * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
460*3a9fd824SRoger Pau Monné * The router provides a programmable mapping from each link to a GSI.
461*3a9fd824SRoger Pau Monné */
462*3a9fd824SRoger Pau Monné uint8_t route[4];
463*3a9fd824SRoger Pau Monné uint8_t pad0[4];
464*3a9fd824SRoger Pau Monné };
465*3a9fd824SRoger Pau Monné
466*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
467*3a9fd824SRoger Pau Monné
468*3a9fd824SRoger Pau Monné /*
469*3a9fd824SRoger Pau Monné * PIT
470*3a9fd824SRoger Pau Monné */
471*3a9fd824SRoger Pau Monné
472*3a9fd824SRoger Pau Monné struct hvm_hw_pit {
473*3a9fd824SRoger Pau Monné struct hvm_hw_pit_channel {
474*3a9fd824SRoger Pau Monné uint32_t count; /* can be 65536 */
475*3a9fd824SRoger Pau Monné uint16_t latched_count;
476*3a9fd824SRoger Pau Monné uint8_t count_latched;
477*3a9fd824SRoger Pau Monné uint8_t status_latched;
478*3a9fd824SRoger Pau Monné uint8_t status;
479*3a9fd824SRoger Pau Monné uint8_t read_state;
480*3a9fd824SRoger Pau Monné uint8_t write_state;
481*3a9fd824SRoger Pau Monné uint8_t write_latch;
482*3a9fd824SRoger Pau Monné uint8_t rw_mode;
483*3a9fd824SRoger Pau Monné uint8_t mode;
484*3a9fd824SRoger Pau Monné uint8_t bcd; /* not supported */
485*3a9fd824SRoger Pau Monné uint8_t gate; /* timer start */
486*3a9fd824SRoger Pau Monné } channels[3]; /* 3 x 16 bytes */
487*3a9fd824SRoger Pau Monné uint32_t speaker_data_on;
488*3a9fd824SRoger Pau Monné uint32_t pad0;
489*3a9fd824SRoger Pau Monné };
490*3a9fd824SRoger Pau Monné
491*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
492*3a9fd824SRoger Pau Monné
493*3a9fd824SRoger Pau Monné
494*3a9fd824SRoger Pau Monné /*
495*3a9fd824SRoger Pau Monné * RTC
496*3a9fd824SRoger Pau Monné */
497*3a9fd824SRoger Pau Monné
498*3a9fd824SRoger Pau Monné #define RTC_CMOS_SIZE 14
499*3a9fd824SRoger Pau Monné struct hvm_hw_rtc {
500*3a9fd824SRoger Pau Monné /* CMOS bytes */
501*3a9fd824SRoger Pau Monné uint8_t cmos_data[RTC_CMOS_SIZE];
502*3a9fd824SRoger Pau Monné /* Index register for 2-part operations */
503*3a9fd824SRoger Pau Monné uint8_t cmos_index;
504*3a9fd824SRoger Pau Monné uint8_t pad0;
505*3a9fd824SRoger Pau Monné /* RTC offset from host time */
506*3a9fd824SRoger Pau Monné int64_t rtc_offset;
507*3a9fd824SRoger Pau Monné };
508*3a9fd824SRoger Pau Monné
509*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
510*3a9fd824SRoger Pau Monné
511*3a9fd824SRoger Pau Monné
512*3a9fd824SRoger Pau Monné /*
513*3a9fd824SRoger Pau Monné * HPET
514*3a9fd824SRoger Pau Monné */
515*3a9fd824SRoger Pau Monné
516*3a9fd824SRoger Pau Monné #define HPET_TIMER_NUM 3 /* 3 timers supported now */
517*3a9fd824SRoger Pau Monné struct hvm_hw_hpet {
518*3a9fd824SRoger Pau Monné /* Memory-mapped, software visible registers */
519*3a9fd824SRoger Pau Monné uint64_t capability; /* capabilities */
520*3a9fd824SRoger Pau Monné uint64_t res0; /* reserved */
521*3a9fd824SRoger Pau Monné uint64_t config; /* configuration */
522*3a9fd824SRoger Pau Monné uint64_t res1; /* reserved */
523*3a9fd824SRoger Pau Monné uint64_t isr; /* interrupt status reg */
524*3a9fd824SRoger Pau Monné uint64_t res2[25]; /* reserved */
525*3a9fd824SRoger Pau Monné uint64_t mc64; /* main counter */
526*3a9fd824SRoger Pau Monné uint64_t res3; /* reserved */
527*3a9fd824SRoger Pau Monné struct { /* timers */
528*3a9fd824SRoger Pau Monné uint64_t config; /* configuration/cap */
529*3a9fd824SRoger Pau Monné uint64_t cmp; /* comparator */
530*3a9fd824SRoger Pau Monné uint64_t fsb; /* FSB route, not supported now */
531*3a9fd824SRoger Pau Monné uint64_t res4; /* reserved */
532*3a9fd824SRoger Pau Monné } timers[HPET_TIMER_NUM];
533*3a9fd824SRoger Pau Monné uint64_t res5[4*(24-HPET_TIMER_NUM)]; /* reserved, up to 0x3ff */
534*3a9fd824SRoger Pau Monné
535*3a9fd824SRoger Pau Monné /* Hidden register state */
536*3a9fd824SRoger Pau Monné uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
537*3a9fd824SRoger Pau Monné };
538*3a9fd824SRoger Pau Monné
539*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
540*3a9fd824SRoger Pau Monné
541*3a9fd824SRoger Pau Monné
542*3a9fd824SRoger Pau Monné /*
543*3a9fd824SRoger Pau Monné * PM timer
544*3a9fd824SRoger Pau Monné */
545*3a9fd824SRoger Pau Monné
546*3a9fd824SRoger Pau Monné struct hvm_hw_pmtimer {
547*3a9fd824SRoger Pau Monné uint32_t tmr_val; /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
548*3a9fd824SRoger Pau Monné uint16_t pm1a_sts; /* PM1a_EVT_BLK.PM1a_STS: status register */
549*3a9fd824SRoger Pau Monné uint16_t pm1a_en; /* PM1a_EVT_BLK.PM1a_EN: enable register */
550*3a9fd824SRoger Pau Monné };
551*3a9fd824SRoger Pau Monné
552*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
553*3a9fd824SRoger Pau Monné
554*3a9fd824SRoger Pau Monné /*
555*3a9fd824SRoger Pau Monné * MTRR MSRs
556*3a9fd824SRoger Pau Monné */
557*3a9fd824SRoger Pau Monné
558*3a9fd824SRoger Pau Monné struct hvm_hw_mtrr {
559*3a9fd824SRoger Pau Monné #define MTRR_VCNT 8
560*3a9fd824SRoger Pau Monné #define NUM_FIXED_MSR 11
561*3a9fd824SRoger Pau Monné uint64_t msr_pat_cr;
562*3a9fd824SRoger Pau Monné /* mtrr physbase & physmask msr pair*/
563*3a9fd824SRoger Pau Monné uint64_t msr_mtrr_var[MTRR_VCNT*2];
564*3a9fd824SRoger Pau Monné uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
565*3a9fd824SRoger Pau Monné uint64_t msr_mtrr_cap;
566*3a9fd824SRoger Pau Monné uint64_t msr_mtrr_def_type;
567*3a9fd824SRoger Pau Monné };
568*3a9fd824SRoger Pau Monné
569*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
570*3a9fd824SRoger Pau Monné
571*3a9fd824SRoger Pau Monné /*
572*3a9fd824SRoger Pau Monné * The save area of XSAVE/XRSTOR.
573*3a9fd824SRoger Pau Monné */
574*3a9fd824SRoger Pau Monné
575*3a9fd824SRoger Pau Monné struct hvm_hw_cpu_xsave {
576*3a9fd824SRoger Pau Monné uint64_t xfeature_mask; /* Ignored */
577*3a9fd824SRoger Pau Monné uint64_t xcr0; /* Updated by XSETBV */
578*3a9fd824SRoger Pau Monné uint64_t xcr0_accum; /* Updated by XSETBV */
579*3a9fd824SRoger Pau Monné struct {
580*3a9fd824SRoger Pau Monné struct { char x[512]; } fpu_sse;
581*3a9fd824SRoger Pau Monné
582*3a9fd824SRoger Pau Monné struct hvm_hw_cpu_xsave_hdr {
583*3a9fd824SRoger Pau Monné uint64_t xstate_bv; /* Updated by XRSTOR */
584*3a9fd824SRoger Pau Monné uint64_t xcomp_bv; /* Updated by XRSTOR{C,S} */
585*3a9fd824SRoger Pau Monné uint64_t reserved[6];
586*3a9fd824SRoger Pau Monné } xsave_hdr; /* The 64-byte header */
587*3a9fd824SRoger Pau Monné } save_area;
588*3a9fd824SRoger Pau Monné };
589*3a9fd824SRoger Pau Monné
590*3a9fd824SRoger Pau Monné #define CPU_XSAVE_CODE 16
591*3a9fd824SRoger Pau Monné
592*3a9fd824SRoger Pau Monné /*
593*3a9fd824SRoger Pau Monné * Viridian hypervisor context.
594*3a9fd824SRoger Pau Monné */
595*3a9fd824SRoger Pau Monné
596*3a9fd824SRoger Pau Monné struct hvm_viridian_domain_context {
597*3a9fd824SRoger Pau Monné uint64_t hypercall_gpa;
598*3a9fd824SRoger Pau Monné uint64_t guest_os_id;
599*3a9fd824SRoger Pau Monné uint64_t time_ref_count;
600*3a9fd824SRoger Pau Monné uint64_t reference_tsc;
601*3a9fd824SRoger Pau Monné };
602*3a9fd824SRoger Pau Monné
603*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
604*3a9fd824SRoger Pau Monné
605*3a9fd824SRoger Pau Monné struct hvm_viridian_vcpu_context {
606*3a9fd824SRoger Pau Monné uint64_t vp_assist_msr;
607*3a9fd824SRoger Pau Monné uint8_t apic_assist_pending;
608*3a9fd824SRoger Pau Monné uint8_t _pad[7];
609*3a9fd824SRoger Pau Monné uint64_t simp_msr;
610*3a9fd824SRoger Pau Monné uint64_t sint_msr[16];
611*3a9fd824SRoger Pau Monné uint64_t stimer_config_msr[4];
612*3a9fd824SRoger Pau Monné uint64_t stimer_count_msr[4];
613*3a9fd824SRoger Pau Monné };
614*3a9fd824SRoger Pau Monné
615*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);
616*3a9fd824SRoger Pau Monné
617*3a9fd824SRoger Pau Monné struct hvm_vmce_vcpu {
618*3a9fd824SRoger Pau Monné uint64_t caps;
619*3a9fd824SRoger Pau Monné uint64_t mci_ctl2_bank0;
620*3a9fd824SRoger Pau Monné uint64_t mci_ctl2_bank1;
621*3a9fd824SRoger Pau Monné uint64_t mcg_ext_ctl;
622*3a9fd824SRoger Pau Monné };
623*3a9fd824SRoger Pau Monné
624*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
625*3a9fd824SRoger Pau Monné
626*3a9fd824SRoger Pau Monné struct hvm_tsc_adjust {
627*3a9fd824SRoger Pau Monné uint64_t tsc_adjust;
628*3a9fd824SRoger Pau Monné };
629*3a9fd824SRoger Pau Monné
630*3a9fd824SRoger Pau Monné DECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
631*3a9fd824SRoger Pau Monné
632*3a9fd824SRoger Pau Monné
633*3a9fd824SRoger Pau Monné struct hvm_msr {
634*3a9fd824SRoger Pau Monné uint32_t count;
635*3a9fd824SRoger Pau Monné struct hvm_one_msr {
636*3a9fd824SRoger Pau Monné uint32_t index;
637*3a9fd824SRoger Pau Monné uint32_t _rsvd;
638*3a9fd824SRoger Pau Monné uint64_t val;
639*3a9fd824SRoger Pau Monné } msr[XEN_FLEX_ARRAY_DIM];
640*3a9fd824SRoger Pau Monné };
641*3a9fd824SRoger Pau Monné
642*3a9fd824SRoger Pau Monné #define CPU_MSR_CODE 20
643*3a9fd824SRoger Pau Monné
644*3a9fd824SRoger Pau Monné /* Range 22 - 34 (inclusive) reserved for Amazon */
645*3a9fd824SRoger Pau Monné
646*3a9fd824SRoger Pau Monné /*
647*3a9fd824SRoger Pau Monné * Largest type-code in use
648*3a9fd824SRoger Pau Monné */
649*3a9fd824SRoger Pau Monné #define HVM_SAVE_CODE_MAX 20
650*3a9fd824SRoger Pau Monné
651*3a9fd824SRoger Pau Monné #endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
652*3a9fd824SRoger Pau Monné
653*3a9fd824SRoger Pau Monné /*
654*3a9fd824SRoger Pau Monné * Local variables:
655*3a9fd824SRoger Pau Monné * mode: C
656*3a9fd824SRoger Pau Monné * c-file-style: "BSD"
657*3a9fd824SRoger Pau Monné * c-basic-offset: 4
658*3a9fd824SRoger Pau Monné * tab-width: 4
659*3a9fd824SRoger Pau Monné * indent-tabs-mode: nil
660*3a9fd824SRoger Pau Monné * End:
661*3a9fd824SRoger Pau Monné */
662