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 */
41251767Sgibbs    uint32_t gtsc_khz;        /* Guest's TSC frequency in kHz */
42183375Skmacy};
43183375Skmacy
44183375SkmacyDECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
45183375Skmacy
46183375Skmacy
47183375Skmacy/*
48183375Skmacy * Processor
49251767Sgibbs *
50251767Sgibbs * Compat: Pre-3.4 didn't have msr_tsc_aux
51183375Skmacy */
52183375Skmacy
53183375Skmacystruct hvm_hw_cpu {
54183375Skmacy    uint8_t  fpu_regs[512];
55183375Skmacy
56183375Skmacy    uint64_t rax;
57183375Skmacy    uint64_t rbx;
58183375Skmacy    uint64_t rcx;
59183375Skmacy    uint64_t rdx;
60183375Skmacy    uint64_t rbp;
61183375Skmacy    uint64_t rsi;
62183375Skmacy    uint64_t rdi;
63183375Skmacy    uint64_t rsp;
64183375Skmacy    uint64_t r8;
65183375Skmacy    uint64_t r9;
66183375Skmacy    uint64_t r10;
67183375Skmacy    uint64_t r11;
68183375Skmacy    uint64_t r12;
69183375Skmacy    uint64_t r13;
70183375Skmacy    uint64_t r14;
71183375Skmacy    uint64_t r15;
72183375Skmacy
73183375Skmacy    uint64_t rip;
74183375Skmacy    uint64_t rflags;
75183375Skmacy
76183375Skmacy    uint64_t cr0;
77183375Skmacy    uint64_t cr2;
78183375Skmacy    uint64_t cr3;
79183375Skmacy    uint64_t cr4;
80183375Skmacy
81183375Skmacy    uint64_t dr0;
82183375Skmacy    uint64_t dr1;
83183375Skmacy    uint64_t dr2;
84183375Skmacy    uint64_t dr3;
85183375Skmacy    uint64_t dr6;
86183375Skmacy    uint64_t dr7;
87183375Skmacy
88183375Skmacy    uint32_t cs_sel;
89183375Skmacy    uint32_t ds_sel;
90183375Skmacy    uint32_t es_sel;
91183375Skmacy    uint32_t fs_sel;
92183375Skmacy    uint32_t gs_sel;
93183375Skmacy    uint32_t ss_sel;
94183375Skmacy    uint32_t tr_sel;
95183375Skmacy    uint32_t ldtr_sel;
96183375Skmacy
97183375Skmacy    uint32_t cs_limit;
98183375Skmacy    uint32_t ds_limit;
99183375Skmacy    uint32_t es_limit;
100183375Skmacy    uint32_t fs_limit;
101183375Skmacy    uint32_t gs_limit;
102183375Skmacy    uint32_t ss_limit;
103183375Skmacy    uint32_t tr_limit;
104183375Skmacy    uint32_t ldtr_limit;
105183375Skmacy    uint32_t idtr_limit;
106183375Skmacy    uint32_t gdtr_limit;
107183375Skmacy
108183375Skmacy    uint64_t cs_base;
109183375Skmacy    uint64_t ds_base;
110183375Skmacy    uint64_t es_base;
111183375Skmacy    uint64_t fs_base;
112183375Skmacy    uint64_t gs_base;
113183375Skmacy    uint64_t ss_base;
114183375Skmacy    uint64_t tr_base;
115183375Skmacy    uint64_t ldtr_base;
116183375Skmacy    uint64_t idtr_base;
117183375Skmacy    uint64_t gdtr_base;
118183375Skmacy
119183375Skmacy    uint32_t cs_arbytes;
120183375Skmacy    uint32_t ds_arbytes;
121183375Skmacy    uint32_t es_arbytes;
122183375Skmacy    uint32_t fs_arbytes;
123183375Skmacy    uint32_t gs_arbytes;
124183375Skmacy    uint32_t ss_arbytes;
125183375Skmacy    uint32_t tr_arbytes;
126183375Skmacy    uint32_t ldtr_arbytes;
127183375Skmacy
128251767Sgibbs    uint64_t sysenter_cs;
129251767Sgibbs    uint64_t sysenter_esp;
130251767Sgibbs    uint64_t sysenter_eip;
131183375Skmacy
132251767Sgibbs    /* msr for em64t */
133251767Sgibbs    uint64_t shadow_gs;
134251767Sgibbs
135251767Sgibbs    /* msr content saved/restored. */
136251767Sgibbs    uint64_t msr_flags;
137251767Sgibbs    uint64_t msr_lstar;
138251767Sgibbs    uint64_t msr_star;
139251767Sgibbs    uint64_t msr_cstar;
140251767Sgibbs    uint64_t msr_syscall_mask;
141251767Sgibbs    uint64_t msr_efer;
142251767Sgibbs    uint64_t msr_tsc_aux;
143251767Sgibbs
144251767Sgibbs    /* guest's idea of what rdtsc() would return */
145251767Sgibbs    uint64_t tsc;
146251767Sgibbs
147251767Sgibbs    /* pending event, if any */
148251767Sgibbs    union {
149251767Sgibbs        uint32_t pending_event;
150251767Sgibbs        struct {
151251767Sgibbs            uint8_t  pending_vector:8;
152251767Sgibbs            uint8_t  pending_type:3;
153251767Sgibbs            uint8_t  pending_error_valid:1;
154251767Sgibbs            uint32_t pending_reserved:19;
155251767Sgibbs            uint8_t  pending_valid:1;
156251767Sgibbs        };
157251767Sgibbs    };
158251767Sgibbs    /* error code for pending event */
159251767Sgibbs    uint32_t error_code;
160251767Sgibbs};
161251767Sgibbs
162251767Sgibbsstruct hvm_hw_cpu_compat {
163251767Sgibbs    uint8_t  fpu_regs[512];
164251767Sgibbs
165251767Sgibbs    uint64_t rax;
166251767Sgibbs    uint64_t rbx;
167251767Sgibbs    uint64_t rcx;
168251767Sgibbs    uint64_t rdx;
169251767Sgibbs    uint64_t rbp;
170251767Sgibbs    uint64_t rsi;
171251767Sgibbs    uint64_t rdi;
172251767Sgibbs    uint64_t rsp;
173251767Sgibbs    uint64_t r8;
174251767Sgibbs    uint64_t r9;
175251767Sgibbs    uint64_t r10;
176251767Sgibbs    uint64_t r11;
177251767Sgibbs    uint64_t r12;
178251767Sgibbs    uint64_t r13;
179251767Sgibbs    uint64_t r14;
180251767Sgibbs    uint64_t r15;
181251767Sgibbs
182251767Sgibbs    uint64_t rip;
183251767Sgibbs    uint64_t rflags;
184251767Sgibbs
185251767Sgibbs    uint64_t cr0;
186251767Sgibbs    uint64_t cr2;
187251767Sgibbs    uint64_t cr3;
188251767Sgibbs    uint64_t cr4;
189251767Sgibbs
190251767Sgibbs    uint64_t dr0;
191251767Sgibbs    uint64_t dr1;
192251767Sgibbs    uint64_t dr2;
193251767Sgibbs    uint64_t dr3;
194251767Sgibbs    uint64_t dr6;
195251767Sgibbs    uint64_t dr7;
196251767Sgibbs
197251767Sgibbs    uint32_t cs_sel;
198251767Sgibbs    uint32_t ds_sel;
199251767Sgibbs    uint32_t es_sel;
200251767Sgibbs    uint32_t fs_sel;
201251767Sgibbs    uint32_t gs_sel;
202251767Sgibbs    uint32_t ss_sel;
203251767Sgibbs    uint32_t tr_sel;
204251767Sgibbs    uint32_t ldtr_sel;
205251767Sgibbs
206251767Sgibbs    uint32_t cs_limit;
207251767Sgibbs    uint32_t ds_limit;
208251767Sgibbs    uint32_t es_limit;
209251767Sgibbs    uint32_t fs_limit;
210251767Sgibbs    uint32_t gs_limit;
211251767Sgibbs    uint32_t ss_limit;
212251767Sgibbs    uint32_t tr_limit;
213251767Sgibbs    uint32_t ldtr_limit;
214251767Sgibbs    uint32_t idtr_limit;
215251767Sgibbs    uint32_t gdtr_limit;
216251767Sgibbs
217251767Sgibbs    uint64_t cs_base;
218251767Sgibbs    uint64_t ds_base;
219251767Sgibbs    uint64_t es_base;
220251767Sgibbs    uint64_t fs_base;
221251767Sgibbs    uint64_t gs_base;
222251767Sgibbs    uint64_t ss_base;
223251767Sgibbs    uint64_t tr_base;
224251767Sgibbs    uint64_t ldtr_base;
225251767Sgibbs    uint64_t idtr_base;
226251767Sgibbs    uint64_t gdtr_base;
227251767Sgibbs
228251767Sgibbs    uint32_t cs_arbytes;
229251767Sgibbs    uint32_t ds_arbytes;
230251767Sgibbs    uint32_t es_arbytes;
231251767Sgibbs    uint32_t fs_arbytes;
232251767Sgibbs    uint32_t gs_arbytes;
233251767Sgibbs    uint32_t ss_arbytes;
234251767Sgibbs    uint32_t tr_arbytes;
235251767Sgibbs    uint32_t ldtr_arbytes;
236251767Sgibbs
237251767Sgibbs    uint64_t sysenter_cs;
238183375Skmacy    uint64_t sysenter_esp;
239183375Skmacy    uint64_t sysenter_eip;
240183375Skmacy
241183375Skmacy    /* msr for em64t */
242183375Skmacy    uint64_t shadow_gs;
243183375Skmacy
244183375Skmacy    /* msr content saved/restored. */
245183375Skmacy    uint64_t msr_flags;
246183375Skmacy    uint64_t msr_lstar;
247183375Skmacy    uint64_t msr_star;
248183375Skmacy    uint64_t msr_cstar;
249183375Skmacy    uint64_t msr_syscall_mask;
250183375Skmacy    uint64_t msr_efer;
251251767Sgibbs    /*uint64_t msr_tsc_aux; COMPAT */
252183375Skmacy
253183375Skmacy    /* guest's idea of what rdtsc() would return */
254183375Skmacy    uint64_t tsc;
255183375Skmacy
256183375Skmacy    /* pending event, if any */
257183375Skmacy    union {
258183375Skmacy        uint32_t pending_event;
259183375Skmacy        struct {
260183375Skmacy            uint8_t  pending_vector:8;
261183375Skmacy            uint8_t  pending_type:3;
262183375Skmacy            uint8_t  pending_error_valid:1;
263183375Skmacy            uint32_t pending_reserved:19;
264183375Skmacy            uint8_t  pending_valid:1;
265183375Skmacy        };
266183375Skmacy    };
267183375Skmacy    /* error code for pending event */
268183375Skmacy    uint32_t error_code;
269183375Skmacy};
270183375Skmacy
271251767Sgibbsstatic inline int _hvm_hw_fix_cpu(void *h) {
272183375Skmacy
273288917Sroyger    union hvm_hw_cpu_union {
274288917Sroyger        struct hvm_hw_cpu nat;
275288917Sroyger        struct hvm_hw_cpu_compat cmp;
276288917Sroyger    } *ucpu = (union hvm_hw_cpu_union *)h;
277288917Sroyger
278251767Sgibbs    /* If we copy from the end backwards, we should
279251767Sgibbs     * be able to do the modification in-place */
280288917Sroyger    ucpu->nat.error_code = ucpu->cmp.error_code;
281288917Sroyger    ucpu->nat.pending_event = ucpu->cmp.pending_event;
282288917Sroyger    ucpu->nat.tsc = ucpu->cmp.tsc;
283288917Sroyger    ucpu->nat.msr_tsc_aux = 0;
284183375Skmacy
285251767Sgibbs    return 0;
286251767Sgibbs}
287251767Sgibbs
288251767SgibbsDECLARE_HVM_SAVE_TYPE_COMPAT(CPU, 2, struct hvm_hw_cpu, \
289251767Sgibbs                             struct hvm_hw_cpu_compat, _hvm_hw_fix_cpu);
290251767Sgibbs
291183375Skmacy/*
292183375Skmacy * PIC
293183375Skmacy */
294183375Skmacy
295183375Skmacystruct hvm_hw_vpic {
296183375Skmacy    /* IR line bitmasks. */
297183375Skmacy    uint8_t irr;
298183375Skmacy    uint8_t imr;
299183375Skmacy    uint8_t isr;
300183375Skmacy
301183375Skmacy    /* Line IRx maps to IRQ irq_base+x */
302183375Skmacy    uint8_t irq_base;
303183375Skmacy
304183375Skmacy    /*
305183375Skmacy     * Where are we in ICW2-4 initialisation (0 means no init in progress)?
306183375Skmacy     * Bits 0-1 (=x): Next write at A=1 sets ICW(x+1).
307183375Skmacy     * Bit 2: ICW1.IC4  (1 == ICW4 included in init sequence)
308183375Skmacy     * Bit 3: ICW1.SNGL (0 == ICW3 included in init sequence)
309183375Skmacy     */
310183375Skmacy    uint8_t init_state:4;
311183375Skmacy
312183375Skmacy    /* IR line with highest priority. */
313183375Skmacy    uint8_t priority_add:4;
314183375Skmacy
315183375Skmacy    /* Reads from A=0 obtain ISR or IRR? */
316183375Skmacy    uint8_t readsel_isr:1;
317183375Skmacy
318183375Skmacy    /* Reads perform a polling read? */
319183375Skmacy    uint8_t poll:1;
320183375Skmacy
321183375Skmacy    /* Automatically clear IRQs from the ISR during INTA? */
322183375Skmacy    uint8_t auto_eoi:1;
323183375Skmacy
324183375Skmacy    /* Automatically rotate IRQ priorities during AEOI? */
325183375Skmacy    uint8_t rotate_on_auto_eoi:1;
326183375Skmacy
327183375Skmacy    /* Exclude slave inputs when considering in-service IRQs? */
328183375Skmacy    uint8_t special_fully_nested_mode:1;
329183375Skmacy
330183375Skmacy    /* Special mask mode excludes masked IRs from AEOI and priority checks. */
331183375Skmacy    uint8_t special_mask_mode:1;
332183375Skmacy
333183375Skmacy    /* Is this a master PIC or slave PIC? (NB. This is not programmable.) */
334183375Skmacy    uint8_t is_master:1;
335183375Skmacy
336183375Skmacy    /* Edge/trigger selection. */
337183375Skmacy    uint8_t elcr;
338183375Skmacy
339183375Skmacy    /* Virtual INT output. */
340183375Skmacy    uint8_t int_output;
341183375Skmacy};
342183375Skmacy
343183375SkmacyDECLARE_HVM_SAVE_TYPE(PIC, 3, struct hvm_hw_vpic);
344183375Skmacy
345183375Skmacy
346183375Skmacy/*
347183375Skmacy * IO-APIC
348183375Skmacy */
349183375Skmacy
350183375Skmacy#define VIOAPIC_NUM_PINS  48 /* 16 ISA IRQs, 32 non-legacy PCI IRQS. */
351183375Skmacy
352183375Skmacystruct hvm_hw_vioapic {
353183375Skmacy    uint64_t base_address;
354183375Skmacy    uint32_t ioregsel;
355183375Skmacy    uint32_t id;
356183375Skmacy    union vioapic_redir_entry
357183375Skmacy    {
358183375Skmacy        uint64_t bits;
359183375Skmacy        struct {
360183375Skmacy            uint8_t vector;
361183375Skmacy            uint8_t delivery_mode:3;
362183375Skmacy            uint8_t dest_mode:1;
363183375Skmacy            uint8_t delivery_status:1;
364183375Skmacy            uint8_t polarity:1;
365183375Skmacy            uint8_t remote_irr:1;
366183375Skmacy            uint8_t trig_mode:1;
367183375Skmacy            uint8_t mask:1;
368183375Skmacy            uint8_t reserve:7;
369183375Skmacy            uint8_t reserved[4];
370183375Skmacy            uint8_t dest_id;
371183375Skmacy        } fields;
372183375Skmacy    } redirtbl[VIOAPIC_NUM_PINS];
373183375Skmacy};
374183375Skmacy
375183375SkmacyDECLARE_HVM_SAVE_TYPE(IOAPIC, 4, struct hvm_hw_vioapic);
376183375Skmacy
377183375Skmacy
378183375Skmacy/*
379183375Skmacy * LAPIC
380183375Skmacy */
381183375Skmacy
382183375Skmacystruct hvm_hw_lapic {
383183375Skmacy    uint64_t             apic_base_msr;
384183375Skmacy    uint32_t             disabled; /* VLAPIC_xx_DISABLED */
385183375Skmacy    uint32_t             timer_divisor;
386251767Sgibbs    uint64_t             tdt_msr;
387183375Skmacy};
388183375Skmacy
389183375SkmacyDECLARE_HVM_SAVE_TYPE(LAPIC, 5, struct hvm_hw_lapic);
390183375Skmacy
391183375Skmacystruct hvm_hw_lapic_regs {
392183375Skmacy    uint8_t data[1024];
393183375Skmacy};
394183375Skmacy
395183375SkmacyDECLARE_HVM_SAVE_TYPE(LAPIC_REGS, 6, struct hvm_hw_lapic_regs);
396183375Skmacy
397183375Skmacy
398183375Skmacy/*
399183375Skmacy * IRQs
400183375Skmacy */
401183375Skmacy
402183375Skmacystruct hvm_hw_pci_irqs {
403183375Skmacy    /*
404183375Skmacy     * Virtual interrupt wires for a single PCI bus.
405183375Skmacy     * Indexed by: device*4 + INTx#.
406183375Skmacy     */
407183375Skmacy    union {
408251767Sgibbs        unsigned long i[16 / sizeof (unsigned long)]; /* DECLARE_BITMAP(i, 32*4); */
409183375Skmacy        uint64_t pad[2];
410183375Skmacy    };
411183375Skmacy};
412183375Skmacy
413183375SkmacyDECLARE_HVM_SAVE_TYPE(PCI_IRQ, 7, struct hvm_hw_pci_irqs);
414183375Skmacy
415183375Skmacystruct hvm_hw_isa_irqs {
416183375Skmacy    /*
417183375Skmacy     * Virtual interrupt wires for ISA devices.
418183375Skmacy     * Indexed by ISA IRQ (assumes no ISA-device IRQ sharing).
419183375Skmacy     */
420183375Skmacy    union {
421251767Sgibbs        unsigned long i[1];  /* DECLARE_BITMAP(i, 16); */
422183375Skmacy        uint64_t pad[1];
423183375Skmacy    };
424183375Skmacy};
425183375Skmacy
426183375SkmacyDECLARE_HVM_SAVE_TYPE(ISA_IRQ, 8, struct hvm_hw_isa_irqs);
427183375Skmacy
428183375Skmacystruct hvm_hw_pci_link {
429183375Skmacy    /*
430183375Skmacy     * PCI-ISA interrupt router.
431183375Skmacy     * Each PCI <device:INTx#> is 'wire-ORed' into one of four links using
432183375Skmacy     * the traditional 'barber's pole' mapping ((device + INTx#) & 3).
433183375Skmacy     * The router provides a programmable mapping from each link to a GSI.
434183375Skmacy     */
435183375Skmacy    uint8_t route[4];
436183375Skmacy    uint8_t pad0[4];
437183375Skmacy};
438183375Skmacy
439183375SkmacyDECLARE_HVM_SAVE_TYPE(PCI_LINK, 9, struct hvm_hw_pci_link);
440183375Skmacy
441183375Skmacy/*
442183375Skmacy *  PIT
443183375Skmacy */
444183375Skmacy
445183375Skmacystruct hvm_hw_pit {
446183375Skmacy    struct hvm_hw_pit_channel {
447183375Skmacy        uint32_t count; /* can be 65536 */
448183375Skmacy        uint16_t latched_count;
449183375Skmacy        uint8_t count_latched;
450183375Skmacy        uint8_t status_latched;
451183375Skmacy        uint8_t status;
452183375Skmacy        uint8_t read_state;
453183375Skmacy        uint8_t write_state;
454183375Skmacy        uint8_t write_latch;
455183375Skmacy        uint8_t rw_mode;
456183375Skmacy        uint8_t mode;
457183375Skmacy        uint8_t bcd; /* not supported */
458183375Skmacy        uint8_t gate; /* timer start */
459183375Skmacy    } channels[3];  /* 3 x 16 bytes */
460183375Skmacy    uint32_t speaker_data_on;
461183375Skmacy    uint32_t pad0;
462183375Skmacy};
463183375Skmacy
464183375SkmacyDECLARE_HVM_SAVE_TYPE(PIT, 10, struct hvm_hw_pit);
465183375Skmacy
466183375Skmacy
467183375Skmacy/*
468183375Skmacy * RTC
469183375Skmacy */
470183375Skmacy
471183375Skmacy#define RTC_CMOS_SIZE 14
472183375Skmacystruct hvm_hw_rtc {
473183375Skmacy    /* CMOS bytes */
474183375Skmacy    uint8_t cmos_data[RTC_CMOS_SIZE];
475183375Skmacy    /* Index register for 2-part operations */
476183375Skmacy    uint8_t cmos_index;
477183375Skmacy    uint8_t pad0;
478183375Skmacy};
479183375Skmacy
480183375SkmacyDECLARE_HVM_SAVE_TYPE(RTC, 11, struct hvm_hw_rtc);
481183375Skmacy
482183375Skmacy
483183375Skmacy/*
484183375Skmacy * HPET
485183375Skmacy */
486183375Skmacy
487183375Skmacy#define HPET_TIMER_NUM     3    /* 3 timers supported now */
488183375Skmacystruct hvm_hw_hpet {
489183375Skmacy    /* Memory-mapped, software visible registers */
490183375Skmacy    uint64_t capability;        /* capabilities */
491183375Skmacy    uint64_t res0;              /* reserved */
492183375Skmacy    uint64_t config;            /* configuration */
493183375Skmacy    uint64_t res1;              /* reserved */
494183375Skmacy    uint64_t isr;               /* interrupt status reg */
495183375Skmacy    uint64_t res2[25];          /* reserved */
496183375Skmacy    uint64_t mc64;              /* main counter */
497183375Skmacy    uint64_t res3;              /* reserved */
498183375Skmacy    struct {                    /* timers */
499183375Skmacy        uint64_t config;        /* configuration/cap */
500183375Skmacy        uint64_t cmp;           /* comparator */
501183375Skmacy        uint64_t fsb;           /* FSB route, not supported now */
502183375Skmacy        uint64_t res4;          /* reserved */
503183375Skmacy    } timers[HPET_TIMER_NUM];
504183375Skmacy    uint64_t res5[4*(24-HPET_TIMER_NUM)];  /* reserved, up to 0x3ff */
505183375Skmacy
506183375Skmacy    /* Hidden register state */
507183375Skmacy    uint64_t period[HPET_TIMER_NUM]; /* Last value written to comparator */
508183375Skmacy};
509183375Skmacy
510183375SkmacyDECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet);
511183375Skmacy
512183375Skmacy
513183375Skmacy/*
514183375Skmacy * PM timer
515183375Skmacy */
516183375Skmacy
517183375Skmacystruct hvm_hw_pmtimer {
518183375Skmacy    uint32_t tmr_val;   /* PM_TMR_BLK.TMR_VAL: 32bit free-running counter */
519183375Skmacy    uint16_t pm1a_sts;  /* PM1a_EVT_BLK.PM1a_STS: status register */
520183375Skmacy    uint16_t pm1a_en;   /* PM1a_EVT_BLK.PM1a_EN: enable register */
521183375Skmacy};
522183375Skmacy
523183375SkmacyDECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer);
524183375Skmacy
525183375Skmacy/*
526183375Skmacy * MTRR MSRs
527183375Skmacy */
528183375Skmacy
529183375Skmacystruct hvm_hw_mtrr {
530183375Skmacy#define MTRR_VCNT 8
531183375Skmacy#define NUM_FIXED_MSR 11
532183375Skmacy    uint64_t msr_pat_cr;
533183375Skmacy    /* mtrr physbase & physmask msr pair*/
534183375Skmacy    uint64_t msr_mtrr_var[MTRR_VCNT*2];
535183375Skmacy    uint64_t msr_mtrr_fixed[NUM_FIXED_MSR];
536183375Skmacy    uint64_t msr_mtrr_cap;
537183375Skmacy    uint64_t msr_mtrr_def_type;
538183375Skmacy};
539183375Skmacy
540183375SkmacyDECLARE_HVM_SAVE_TYPE(MTRR, 14, struct hvm_hw_mtrr);
541183375Skmacy
542251767Sgibbs/*
543251767Sgibbs * The save area of XSAVE/XRSTOR.
544251767Sgibbs */
545251767Sgibbs
546251767Sgibbsstruct hvm_hw_cpu_xsave {
547288917Sroyger    uint64_t xfeature_mask;        /* Ignored */
548251767Sgibbs    uint64_t xcr0;                 /* Updated by XSETBV */
549251767Sgibbs    uint64_t xcr0_accum;           /* Updated by XSETBV */
550251767Sgibbs    struct {
551251767Sgibbs        struct { char x[512]; } fpu_sse;
552251767Sgibbs
553251767Sgibbs        struct {
554251767Sgibbs            uint64_t xstate_bv;         /* Updated by XRSTOR */
555251767Sgibbs            uint64_t reserved[7];
556251767Sgibbs        } xsave_hdr;                    /* The 64-byte header */
557251767Sgibbs
558251767Sgibbs        struct { char x[0]; } ymm;    /* YMM */
559251767Sgibbs    } save_area;
560251767Sgibbs};
561251767Sgibbs
562251767Sgibbs#define CPU_XSAVE_CODE  16
563251767Sgibbs
564251767Sgibbs/*
565251767Sgibbs * Viridian hypervisor context.
566251767Sgibbs */
567251767Sgibbs
568251767Sgibbsstruct hvm_viridian_domain_context {
569251767Sgibbs    uint64_t hypercall_gpa;
570251767Sgibbs    uint64_t guest_os_id;
571288917Sroyger    uint64_t time_ref_count;
572288917Sroyger    uint64_t reference_tsc;
573251767Sgibbs};
574251767Sgibbs
575251767SgibbsDECLARE_HVM_SAVE_TYPE(VIRIDIAN_DOMAIN, 15, struct hvm_viridian_domain_context);
576251767Sgibbs
577251767Sgibbsstruct hvm_viridian_vcpu_context {
578251767Sgibbs    uint64_t apic_assist;
579251767Sgibbs};
580251767Sgibbs
581251767SgibbsDECLARE_HVM_SAVE_TYPE(VIRIDIAN_VCPU, 17, struct hvm_viridian_vcpu_context);
582251767Sgibbs
583251767Sgibbsstruct hvm_vmce_vcpu {
584251767Sgibbs    uint64_t caps;
585288917Sroyger    uint64_t mci_ctl2_bank0;
586288917Sroyger    uint64_t mci_ctl2_bank1;
587251767Sgibbs};
588251767Sgibbs
589251767SgibbsDECLARE_HVM_SAVE_TYPE(VMCE_VCPU, 18, struct hvm_vmce_vcpu);
590251767Sgibbs
591288917Sroygerstruct hvm_tsc_adjust {
592288917Sroyger    uint64_t tsc_adjust;
593288917Sroyger};
594288917Sroyger
595288917SroygerDECLARE_HVM_SAVE_TYPE(TSC_ADJUST, 19, struct hvm_tsc_adjust);
596288917Sroyger
597288917Sroyger
598288917Sroygerstruct hvm_msr {
599288917Sroyger    uint32_t count;
600288917Sroyger    struct hvm_one_msr {
601288917Sroyger        uint32_t index;
602288917Sroyger        uint32_t _rsvd;
603288917Sroyger        uint64_t val;
604288917Sroyger#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
605288917Sroyger    } msr[];
606288917Sroyger#elif defined(__GNUC__)
607288917Sroyger    } msr[0];
608288917Sroyger#else
609288917Sroyger    } msr[1 /* variable size */];
610288917Sroyger#endif
611288917Sroyger};
612288917Sroyger
613288917Sroyger#define CPU_MSR_CODE  20
614288917Sroyger
615183375Skmacy/*
616183375Skmacy * Largest type-code in use
617183375Skmacy */
618288917Sroyger#define HVM_SAVE_CODE_MAX 20
619183375Skmacy
620183375Skmacy#endif /* __XEN_PUBLIC_HVM_SAVE_X86_H__ */
621288917Sroyger
622288917Sroyger/*
623288917Sroyger * Local variables:
624288917Sroyger * mode: C
625288917Sroyger * c-file-style: "BSD"
626288917Sroyger * c-basic-offset: 4
627288917Sroyger * tab-width: 4
628288917Sroyger * indent-tabs-mode: nil
629288917Sroyger * End:
630288917Sroyger */
631