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