1183375Skmacy/*
2183375Skmacy * Structure definitions for HVM state that is held by Xen and must
3183375Skmacy * be saved along with the domain's memory and device-model state.
4183375Skmacy *
5183375Skmacy * Copyright (c) 2007 XenSource Ltd.
6183375Skmacy *
7183375Skmacy * Permission is hereby granted, free of charge, to any person obtaining a copy
8183375Skmacy * of this software and associated documentation files (the "Software"), to
9183375Skmacy * deal in the Software without restriction, including without limitation the
10183375Skmacy * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11183375Skmacy * sell copies of the Software, and to permit persons to whom the Software is
12183375Skmacy * furnished to do so, subject to the following conditions:
13183375Skmacy *
14183375Skmacy * The above copyright notice and this permission notice shall be included in
15183375Skmacy * all copies or substantial portions of the Software.
16183375Skmacy *
17183375Skmacy * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18183375Skmacy * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19183375Skmacy * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20183375Skmacy * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21183375Skmacy * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22183375Skmacy * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23183375Skmacy * DEALINGS IN THE SOFTWARE.
24183375Skmacy */
25183375Skmacy
26183375Skmacy#ifndef __XEN_PUBLIC_HVM_SAVE_X86_H__
27183375Skmacy#define __XEN_PUBLIC_HVM_SAVE_X86_H__
28183375Skmacy
29183375Skmacy/*
30183375Skmacy * Save/restore header: general info about the save file.
31183375Skmacy */
32183375Skmacy
33183375Skmacy#define HVM_FILE_MAGIC   0x54381286
34183375Skmacy#define HVM_FILE_VERSION 0x00000001
35183375Skmacy
36183375Skmacystruct hvm_save_header {
37183375Skmacy    uint32_t magic;             /* Must be HVM_FILE_MAGIC */
38183375Skmacy    uint32_t version;           /* File format version */
39183375Skmacy    uint64_t changeset;         /* Version of Xen that saved this file */
40183375Skmacy    uint32_t cpuid;             /* CPUID[0x01][%eax] on the saving machine */
41183375Skmacy    uint32_t pad0;
42183375Skmacy};
43183375Skmacy
44183375SkmacyDECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
45183375Skmacy
46183375Skmacy
47183375Skmacy/*
48183375Skmacy * Processor
49183375Skmacy */
50183375Skmacy
51183375Skmacystruct hvm_hw_cpu {
52183375Skmacy    uint8_t  fpu_regs[512];
53183375Skmacy
54183375Skmacy    uint64_t rax;
55183375Skmacy    uint64_t rbx;
56183375Skmacy    uint64_t rcx;
57183375Skmacy    uint64_t rdx;
58183375Skmacy    uint64_t rbp;
59183375Skmacy    uint64_t rsi;
60183375Skmacy    uint64_t rdi;
61183375Skmacy    uint64_t rsp;
62183375Skmacy    uint64_t r8;
63183375Skmacy    uint64_t r9;
64183375Skmacy    uint64_t r10;
65183375Skmacy    uint64_t r11;
66183375Skmacy    uint64_t r12;
67183375Skmacy    uint64_t r13;
68183375Skmacy    uint64_t r14;
69183375Skmacy    uint64_t r15;
70183375Skmacy
71183375Skmacy    uint64_t rip;
72183375Skmacy    uint64_t rflags;
73183375Skmacy
74183375Skmacy    uint64_t cr0;
75183375Skmacy    uint64_t cr2;
76183375Skmacy    uint64_t cr3;
77183375Skmacy    uint64_t cr4;
78183375Skmacy
79183375Skmacy    uint64_t dr0;
80183375Skmacy    uint64_t dr1;
81183375Skmacy    uint64_t dr2;
82183375Skmacy    uint64_t dr3;
83183375Skmacy    uint64_t dr6;
84183375Skmacy    uint64_t dr7;
85183375Skmacy
86183375Skmacy    uint32_t cs_sel;
87183375Skmacy    uint32_t ds_sel;
88183375Skmacy    uint32_t es_sel;
89183375Skmacy    uint32_t fs_sel;
90183375Skmacy    uint32_t gs_sel;
91183375Skmacy    uint32_t ss_sel;
92183375Skmacy    uint32_t tr_sel;
93183375Skmacy    uint32_t ldtr_sel;
94183375Skmacy
95183375Skmacy    uint32_t cs_limit;
96183375Skmacy    uint32_t ds_limit;
97183375Skmacy    uint32_t es_limit;
98183375Skmacy    uint32_t fs_limit;
99183375Skmacy    uint32_t gs_limit;
100183375Skmacy    uint32_t ss_limit;
101183375Skmacy    uint32_t tr_limit;
102183375Skmacy    uint32_t ldtr_limit;
103183375Skmacy    uint32_t idtr_limit;
104183375Skmacy    uint32_t gdtr_limit;
105183375Skmacy
106183375Skmacy    uint64_t cs_base;
107183375Skmacy    uint64_t ds_base;
108183375Skmacy    uint64_t es_base;
109183375Skmacy    uint64_t fs_base;
110183375Skmacy    uint64_t gs_base;
111183375Skmacy    uint64_t ss_base;
112183375Skmacy    uint64_t tr_base;
113183375Skmacy    uint64_t ldtr_base;
114183375Skmacy    uint64_t idtr_base;
115183375Skmacy    uint64_t gdtr_base;
116183375Skmacy
117183375Skmacy    uint32_t cs_arbytes;
118183375Skmacy    uint32_t ds_arbytes;
119183375Skmacy    uint32_t es_arbytes;
120183375Skmacy    uint32_t fs_arbytes;
121183375Skmacy    uint32_t gs_arbytes;
122183375Skmacy    uint32_t ss_arbytes;
123183375Skmacy    uint32_t tr_arbytes;
124183375Skmacy    uint32_t ldtr_arbytes;
125183375Skmacy
126183375Skmacy    uint32_t sysenter_cs;
127183375Skmacy    uint32_t padding0;
128183375Skmacy
129183375Skmacy    uint64_t sysenter_esp;
130183375Skmacy    uint64_t sysenter_eip;
131183375Skmacy
132183375Skmacy    /* msr for em64t */
133183375Skmacy    uint64_t shadow_gs;
134183375Skmacy
135183375Skmacy    /* msr content saved/restored. */
136183375Skmacy    uint64_t msr_flags;
137183375Skmacy    uint64_t msr_lstar;
138183375Skmacy    uint64_t msr_star;
139183375Skmacy    uint64_t msr_cstar;
140183375Skmacy    uint64_t msr_syscall_mask;
141183375Skmacy    uint64_t msr_efer;
142183375Skmacy
143183375Skmacy    /* guest's idea of what rdtsc() would return */
144183375Skmacy    uint64_t tsc;
145183375Skmacy
146183375Skmacy    /* pending event, if any */
147183375Skmacy    union {
148183375Skmacy        uint32_t pending_event;
149183375Skmacy        struct {
150183375Skmacy            uint8_t  pending_vector:8;
151183375Skmacy            uint8_t  pending_type:3;
152183375Skmacy            uint8_t  pending_error_valid:1;
153183375Skmacy            uint32_t pending_reserved:19;
154183375Skmacy            uint8_t  pending_valid:1;
155183375Skmacy        };
156183375Skmacy    };
157183375Skmacy    /* error code for pending event */
158183375Skmacy    uint32_t error_code;
159183375Skmacy};
160183375Skmacy
161183375SkmacyDECLARE_HVM_SAVE_TYPE(CPU, 2, struct hvm_hw_cpu);
162183375Skmacy
163183375Skmacy
164183375Skmacy/*
165183375Skmacy * PIC
166183375Skmacy */
167183375Skmacy
168183375Skmacystruct hvm_hw_vpic {
169183375Skmacy    /* IR line bitmasks. */
170183375Skmacy    uint8_t irr;
171183375Skmacy    uint8_t imr;
172183375Skmacy    uint8_t isr;
173183375Skmacy
174183375Skmacy    /* Line IRx maps to IRQ irq_base+x */
175183375Skmacy    uint8_t irq_base;
176183375Skmacy
177183375Skmacy    /*
178183375Skmacy     * Where are we in ICW2-4 initialisation (0 means no init in progress)?
179183375Skmacy     * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
180183375Skmacy     * Bit 2: ICW1.IC4  (1 == ICW4 included in init sequence)
181183375Skmacy     * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
182183375Skmacy     */
183183375Skmacy    uint8_t init_state:4;
184183375Skmacy
185183375Skmacy    /* IR line with highest priority. */
186183375Skmacy    uint8_t priority_add:4;
187183375Skmacy
188183375Skmacy    /* Reads from A=0 obtain ISR or IRR? */
189183375Skmacy    uint8_t readsel_isr:1;
190183375Skmacy
191183375Skmacy    /* Reads perform a polling read? */
192183375Skmacy    uint8_t poll:1;
193183375Skmacy
194183375Skmacy    /* Automatically clear IRQs from the ISR during INTA? */
195183375Skmacy    uint8_t auto_eoi:1;
196183375Skmacy
197183375Skmacy    /* Automatically rotate IRQ priorities during AEOI? */
198183375Skmacy    uint8_t rotate_on_auto_eoi:1;
199183375Skmacy
200183375Skmacy    /* Exclude slave inputs when considering in-service IRQs? */
201183375Skmacy    uint8_t special_fully_nested_mode:1;
202183375Skmacy
203183375Skmacy    /* Special mask mode excludes masked IRs from AEOI and priority checks. */
204183375Skmacy    uint8_t special_mask_mode:1;
205183375Skmacy
206183375Skmacy    /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
207183375Skmacy    uint8_t is_master:1;
208183375Skmacy
209183375Skmacy    /* Edge/trigger selection. */
210183375Skmacy    uint8_t elcr;
211183375Skmacy
212183375Skmacy    /* Virtual INT output. */
213183375Skmacy    uint8_t int_output;
214183375Skmacy};
215183375Skmacy
216183375SkmacyDECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
217183375Skmacy
218183375Skmacy
219183375Skmacy/*
220183375Skmacy * IO-APIC
221183375Skmacy */
222183375Skmacy
223183375Skmacy#ifdef __ia64__
224183375Skmacy#define VIOAPIC_IS_IOSAPIC 1
225183375Skmacy#define VIOAPIC_NUM_PINS  24
226183375Skmacy#else
227183375Skmacy#define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
228183375Skmacy#endif
229183375Skmacy
230183375Skmacystruct hvm_hw_vioapic {
231183375Skmacy    uint64_t base_address;
232183375Skmacy    uint32_t ioregsel;
233183375Skmacy    uint32_t id;
234183375Skmacy    union vioapic_redir_entry
235183375Skmacy    {
236183375Skmacy        uint64_t bits;
237183375Skmacy        struct {
238183375Skmacy            uint8_t vector;
239183375Skmacy            uint8_t delivery_mode:3;
240183375Skmacy            uint8_t dest_mode:1;
241183375Skmacy            uint8_t delivery_status:1;
242183375Skmacy            uint8_t polarity:1;
243183375Skmacy            uint8_t remote_irr:1;
244183375Skmacy            uint8_t trig_mode:1;
245183375Skmacy            uint8_t mask:1;
246183375Skmacy            uint8_t reserve:7;
247183375Skmacy#if !VIOAPIC_IS_IOSAPIC
248183375Skmacy            uint8_t reserved[4];
249183375Skmacy            uint8_t dest_id;
250183375Skmacy#else
251183375Skmacy            uint8_t reserved[3];
252183375Skmacy            uint16_t dest_id;
253183375Skmacy#endif
254183375Skmacy        } fields;
255183375Skmacy    } redirtbl[VIOAPIC_NUM_PINS];
256183375Skmacy};
257183375Skmacy
258183375SkmacyDECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
259183375Skmacy
260183375Skmacy
261183375Skmacy/*
262183375Skmacy * LAPIC
263183375Skmacy */
264183375Skmacy
265183375Skmacystruct hvm_hw_lapic {
266183375Skmacy    uint64_t             apic_base_msr;
267183375Skmacy    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
268183375Skmacy    uint32_t             timer_divisor;
269183375Skmacy};
270183375Skmacy
271183375SkmacyDECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
272183375Skmacy
273183375Skmacystruct hvm_hw_lapic_regs {
274183375Skmacy    uint8_t data[1024];
275183375Skmacy};
276183375Skmacy
277183375SkmacyDECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
278183375Skmacy
279183375Skmacy
280183375Skmacy/*
281183375Skmacy * IRQs
282183375Skmacy */
283183375Skmacy
284183375Skmacystruct hvm_hw_pci_irqs {
285183375Skmacy    /*
286183375Skmacy     * Virtual interrupt wires for a single PCI bus.
287183375Skmacy     * Indexed by: device*4 + INTx#.
288183375Skmacy     */
289183375Skmacy    union {
290183375Skmacy        DECLARE_BITMAP(i, 32*4);
291183375Skmacy        uint64_t pad[2];
292183375Skmacy    };
293183375Skmacy};
294183375Skmacy
295183375SkmacyDECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
296183375Skmacy
297183375Skmacystruct hvm_hw_isa_irqs {
298183375Skmacy    /*
299183375Skmacy     * Virtual interrupt wires for ISA devices.
300183375Skmacy     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
301183375Skmacy     */
302183375Skmacy    union {
303183375Skmacy        DECLARE_BITMAP(i, 16);
304183375Skmacy        uint64_t pad[1];
305183375Skmacy    };
306183375Skmacy};
307183375Skmacy
308183375SkmacyDECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
309183375Skmacy
310183375Skmacystruct hvm_hw_pci_link {
311183375Skmacy    /*
312183375Skmacy     * PCI-ISA interrupt router.
313183375Skmacy     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
314183375Skmacy     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
315183375Skmacy     * The router provides a programmable mapping from each link to a GSI.
316183375Skmacy     */
317183375Skmacy    uint8_t route[4];
318183375Skmacy    uint8_t pad0[4];
319183375Skmacy};
320183375Skmacy
321183375SkmacyDECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
322183375Skmacy
323183375Skmacy/*
324183375Skmacy *  PIT
325183375Skmacy */
326183375Skmacy
327183375Skmacystruct hvm_hw_pit {
328183375Skmacy    struct hvm_hw_pit_channel {
329183375Skmacy        uint32_t count; /* can be 65536 */
330183375Skmacy        uint16_t latched_count;
331183375Skmacy        uint8_t count_latched;
332183375Skmacy        uint8_t status_latched;
333183375Skmacy        uint8_t status;
334183375Skmacy        uint8_t read_state;
335183375Skmacy        uint8_t write_state;
336183375Skmacy        uint8_t write_latch;
337183375Skmacy        uint8_t rw_mode;
338183375Skmacy        uint8_t mode;
339183375Skmacy        uint8_t bcd; /* not supported */
340183375Skmacy        uint8_t gate; /* timer start */
341183375Skmacy    } channels[3];  /* 3 x 16 bytes */
342183375Skmacy    uint32_t speaker_data_on;
343183375Skmacy    uint32_t pad0;
344183375Skmacy};
345183375Skmacy
346183375SkmacyDECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
347183375Skmacy
348183375Skmacy
349183375Skmacy/*
350183375Skmacy * RTC
351183375Skmacy */
352183375Skmacy
353183375Skmacy#define RTC_CMOS_SIZE 14
354183375Skmacystruct hvm_hw_rtc {
355183375Skmacy    /* CMOS bytes */
356183375Skmacy    uint8_t cmos_data[RTC_CMOS_SIZE];
357183375Skmacy    /* Index register for 2-part operations */
358183375Skmacy    uint8_t cmos_index;
359183375Skmacy    uint8_t pad0;
360183375Skmacy};
361183375Skmacy
362183375SkmacyDECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
363183375Skmacy
364183375Skmacy
365183375Skmacy/*
366183375Skmacy * HPET
367183375Skmacy */
368183375Skmacy
369183375Skmacy#define HPET_TIMER_NUM     3    /* 3 timers supported now */
370183375Skmacystruct hvm_hw_hpet {
371183375Skmacy    /* Memory-mapped, software visible registers */
372183375Skmacy    uint64_t capability;        /* capabilities */
373183375Skmacy    uint64_t res0;              /* reserved */
374183375Skmacy    uint64_t config;            /* configuration */
375183375Skmacy    uint64_t res1;              /* reserved */
376183375Skmacy    uint64_t isr;               /* interrupt status reg */
377183375Skmacy    uint64_t res2[25];          /* reserved */
378183375Skmacy    uint64_t mc64;              /* main counter */
379183375Skmacy    uint64_t res3;              /* reserved */
380183375Skmacy    struct {                    /* timers */
381183375Skmacy        uint64_t config;        /* configuration/cap */
382183375Skmacy        uint64_t cmp;           /* comparator */
383183375Skmacy        uint64_t fsb;           /* FSB route, not supported now */
384183375Skmacy        uint64_t res4;          /* reserved */
385183375Skmacy    } timers[HPET_TIMER_NUM];
386183375Skmacy    uint64_t res5[4*(24-HPET_TIMER_NUM)];  /* reserved, up to 0x3ff */
387183375Skmacy
388183375Skmacy    /* Hidden register state */
389183375Skmacy    uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
390183375Skmacy};
391183375Skmacy
392183375SkmacyDECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
393183375Skmacy
394183375Skmacy
395183375Skmacy/*
396183375Skmacy * PM timer
397183375Skmacy */
398183375Skmacy
399183375Skmacystruct hvm_hw_pmtimer {
400183375Skmacy    uint32_t tmr_val;   /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
401183375Skmacy    uint16_t pm1a_sts;  /* PM1a_EVT_BLK.PM1a_STS: status register */
402183375Skmacy    uint16_t pm1a_en;   /* PM1a_EVT_BLK.PM1a_EN: enable register */
403183375Skmacy};
404183375Skmacy
405183375SkmacyDECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
406183375Skmacy
407183375Skmacy/*
408183375Skmacy * MTRR MSRs
409183375Skmacy */
410183375Skmacy
411183375Skmacystruct hvm_hw_mtrr {
412183375Skmacy#define MTRR_VCNT 8
413183375Skmacy#define NUM_FIXED_MSR 11
414183375Skmacy    uint64_t msr_pat_cr;
415183375Skmacy    /* mtrr physbase & physmask msr pair*/
416183375Skmacy    uint64_t msr_mtrr_var[MTRR_VCNT*2];
417183375Skmacy    uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
418183375Skmacy    uint64_t msr_mtrr_cap;
419183375Skmacy    uint64_t msr_mtrr_def_type;
420183375Skmacy};
421183375Skmacy
422183375SkmacyDECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
423183375Skmacy
424183375Skmacy/*
425183375Skmacy * Largest type-code in use
426183375Skmacy */
427183375Skmacy#define HVM_SAVE_CODE_MAX 14
428183375Skmacy
429183375Skmacy#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
430