[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Save/restore cleanups 01: PIT
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1169291858 0 # Node ID 56228886421d877623cdd27e68d6e5b6d1592946 # Parent dcb145f858e32a1d310a5558d4e12bb0521a625d [HVM] Save/restore cleanups 01: PIT Define public structure for the saved PIT data and use it instead of a series of explicit loads and stores. Don't save ephemeral Xen timer structs; rebuild them instead. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- xen/arch/x86/domain.c | 7 - xen/arch/x86/hvm/hvm.c | 1 xen/arch/x86/hvm/i8254.c | 255 ++++++++++++++------------------------ xen/arch/x86/hvm/intercept.c | 2 xen/arch/x86/hvm/vioapic.c | 2 xen/include/asm-x86/hvm/support.h | 7 - xen/include/asm-x86/hvm/vpt.h | 26 --- xen/include/public/hvm/save.h | 138 ++++++++++++++++++++ 8 files changed, 255 insertions(+), 183 deletions(-) diff -r dcb145f858e3 -r 56228886421d xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/arch/x86/domain.c Sat Jan 20 11:17:38 2007 +0000 @@ -329,9 +329,6 @@ int vcpu_initialise(struct vcpu *v) pae_l3_cache_init(&v->arch.pae_l3_cache); - /* This should move to arch_domain_create(). */ - if ( !is_idle_domain(d) && (v->vcpu_id == 0) ) - pit_init(v, cpu_khz); if ( is_hvm_domain(d) ) { @@ -340,6 +337,10 @@ int vcpu_initialise(struct vcpu *v) } else { + /* PV guests get an emulated PIT too for video BIOSes to use. */ + if ( !is_idle_domain(d) && (v->vcpu_id == 0) ) + pit_init(v, cpu_khz); + v->arch.schedule_tail = continue_nonidle_domain; v->arch.ctxt_switch_from = paravirt_ctxt_switch_from; v->arch.ctxt_switch_to = paravirt_ctxt_switch_to; diff -r dcb145f858e3 -r 56228886421d xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/arch/x86/hvm/hvm.c Sat Jan 20 11:17:38 2007 +0000 @@ -194,6 +194,7 @@ int hvm_vcpu_initialise(struct vcpu *v) if ( v->vcpu_id != 0 ) return 0; + pit_init(v, cpu_khz); rtc_init(v, RTC_PORT(0), RTC_IRQ); pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS); hpet_init(v); diff -r dcb145f858e3 -r 56228886421d xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/arch/x86/hvm/i8254.c Sat Jan 20 11:17:38 2007 +0000 @@ -76,37 +76,42 @@ uint64_t muldiv64(uint64_t a, uint32_t b return res.ll; } -static int pit_get_count(PITChannelState *s) +static int pit_get_count(PITState *s, int channel) { uint64_t d; int counter; - - d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); - switch(s->mode) { + struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; + struct periodic_time *pt = &s->pt[channel]; + + d = muldiv64(hvm_get_guest_time(pt->vcpu) + - c->count_load_time, PIT_FREQ, ticks_per_sec(pt->vcpu)); + switch(c->mode) { case 0: case 1: case 4: case 5: - counter = (s->count - d) & 0xffff; + counter = (c->count - d) & 0xffff; break; case 3: /* XXX: may be incorrect for odd counts */ - counter = s->count - ((2 * d) % s->count); + counter = c->count - ((2 * d) % c->count); break; default: - counter = s->count - (d % s->count); + counter = c->count - (d % c->count); break; } return counter; } /* get pit output bit */ -static int pit_get_out1(PITChannelState *s, int64_t current_time) -{ +int pit_get_out(PITState *pit, int channel, int64_t current_time) +{ + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; uint64_t d; int out; - d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu)); + d = muldiv64(current_time - s->count_load_time, + PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu)); switch(s->mode) { default: case 0: @@ -132,16 +137,11 @@ static int pit_get_out1(PITChannelState return out; } -int pit_get_out(PITState *pit, int channel, int64_t current_time) -{ - PITChannelState *s = &pit->channels[channel]; - return pit_get_out1(s, current_time); -} - /* val must be 0 or 1 */ void pit_set_gate(PITState *pit, int channel, int val) { - PITChannelState *s = &pit->channels[channel]; + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; + struct periodic_time *pt = &pit->pt[channel]; switch(s->mode) { default: @@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha case 5: if (s->gate < val) { /* restart counting on rising edge */ - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); + s->count_load_time = hvm_get_guest_time(pt->vcpu); // pit_irq_timer_update(s, s->count_load_time); } break; @@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha case 3: if (s->gate < val) { /* restart counting on rising edge */ - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); + s->count_load_time = hvm_get_guest_time(pt->vcpu); // pit_irq_timer_update(s, s->count_load_time); } /* XXX: disable/enable counting */ @@ -172,23 +172,25 @@ void pit_set_gate(PITState *pit, int cha int pit_get_gate(PITState *pit, int channel) { - PITChannelState *s = &pit->channels[channel]; - return s->gate; + return pit->hw.channels[channel].gate; } void pit_time_fired(struct vcpu *v, void *priv) { - PITChannelState *s = priv; + struct hvm_hw_pit_channel *s = priv; s->count_load_time = hvm_get_guest_time(v); } -static inline void pit_load_count(PITChannelState *s, int channel, int val) +static inline void pit_load_count(PITState *pit, int channel, int val) { u32 period; + struct hvm_hw_pit_channel *s = &pit->hw.channels[channel]; + struct periodic_time *pt = &pit->pt[channel]; + struct vcpu *v; if (val == 0) val = 0x10000; - s->count_load_time = hvm_get_guest_time(s->pt.vcpu); + s->count_load_time = hvm_get_guest_time(pt->vcpu); s->count = val; period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ); @@ -204,30 +206,38 @@ static inline void pit_load_count(PITCha (long long)s->count_load_time); #endif + /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */ + if ( likely(pit == ¤t->domain->arch.hvm_domain.pl_time.vpit) ) + v = current; + else + v = container_of(pit, struct domain, + arch.hvm_domain.pl_time.vpit)->vcpu[0]; + switch (s->mode) { case 2: /* create periodic time */ - create_periodic_time(current, &s->pt, period, 0, 0, pit_time_fired, s); + create_periodic_time(v, pt, period, 0, 0, pit_time_fired, s); break; case 1: /* create one shot time */ - create_periodic_time(current, &s->pt, period, 0, 1, pit_time_fired, s); + create_periodic_time(v, pt, period, 0, 1, pit_time_fired, s); #ifdef DEBUG_PIT printk("HVM_PIT: create one shot time.\n"); #endif break; default: - destroy_periodic_time(&s->pt); + destroy_periodic_time(pt); break; } } /* if already latched, do not latch again */ -static void pit_latch_count(PITChannelState *s) -{ - if (!s->count_latched) { - s->latched_count = pit_get_count(s); - s->count_latched = s->rw_mode; +static void pit_latch_count(PITState *s, int channel) +{ + struct hvm_hw_pit_channel *c = &s->hw.channels[channel]; + if (!c->count_latched) { + c->latched_count = pit_get_count(s, channel); + c->count_latched = c->rw_mode; } } @@ -235,7 +245,7 @@ static void pit_ioport_write(void *opaqu { PITState *pit = opaque; int channel, access; - PITChannelState *s; + struct hvm_hw_pit_channel *s; val &= 0xff; addr &= 3; @@ -244,15 +254,15 @@ static void pit_ioport_write(void *opaqu if (channel == 3) { /* read back command */ for(channel = 0; channel < 3; channel++) { - s = &pit->channels[channel]; + s = &pit->hw.channels[channel]; if (val & (2 << channel)) { if (!(val & 0x20)) { - pit_latch_count(s); + pit_latch_count(pit, channel); } if (!(val & 0x10) && !s->status_latched) { /* status latch */ /* XXX: add BCD and null count */ - s->status = (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) | + s->status = (pit_get_out(pit, channel, hvm_get_guest_time(pit->pt[channel].vcpu)) << 7) | (s->rw_mode << 4) | (s->mode << 1) | s->bcd; @@ -261,10 +271,10 @@ static void pit_ioport_write(void *opaqu } } } else { - s = &pit->channels[channel]; + s = &pit->hw.channels[channel]; access = (val >> 4) & 3; if (access == 0) { - pit_latch_count(s); + pit_latch_count(pit, channel); } else { s->rw_mode = access; s->read_state = access; @@ -276,21 +286,21 @@ static void pit_ioport_write(void *opaqu } } } else { - s = &pit->channels[addr]; + s = &pit->hw.channels[addr]; switch(s->write_state) { default: case RW_STATE_LSB: - pit_load_count(s, addr, val); + pit_load_count(pit, addr, val); break; case RW_STATE_MSB: - pit_load_count(s, addr, val << 8); + pit_load_count(pit, addr, val << 8); break; case RW_STATE_WORD0: s->write_latch = val; s->write_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: - pit_load_count(s, addr, s->write_latch | (val << 8)); + pit_load_count(pit, addr, s->write_latch | (val << 8)); s->write_state = RW_STATE_WORD0; break; } @@ -301,10 +311,10 @@ static uint32_t pit_ioport_read(void *op { PITState *pit = opaque; int ret, count; - PITChannelState *s; + struct hvm_hw_pit_channel *s; addr &= 3; - s = &pit->channels[addr]; + s = &pit->hw.channels[addr]; if (s->status_latched) { s->status_latched = 0; ret = s->status; @@ -328,20 +338,20 @@ static uint32_t pit_ioport_read(void *op switch(s->read_state) { default: case RW_STATE_LSB: - count = pit_get_count(s); + count = pit_get_count(pit, addr); ret = count & 0xff; break; case RW_STATE_MSB: - count = pit_get_count(s); + count = pit_get_count(pit, addr); ret = (count >> 8) & 0xff; break; case RW_STATE_WORD0: - count = pit_get_count(s); + count = pit_get_count(pit, addr); ret = count & 0xff; s->read_state = RW_STATE_WORD1; break; case RW_STATE_WORD1: - count = pit_get_count(s); + count = pit_get_count(pit, addr); ret = (count >> 8) & 0xff; s->read_state = RW_STATE_WORD0; break; @@ -352,19 +362,19 @@ static uint32_t pit_ioport_read(void *op void pit_stop_channel0_irq(PITState * pit) { - PITChannelState *s = &pit->channels[0]; - destroy_periodic_time(&s->pt); + destroy_periodic_time(&pit->pt[0]); } #ifdef HVM_DEBUG_SUSPEND static void pit_info(PITState *pit) { - PITChannelState *s; + struct hvm_hw_pit_channel *s; + struct periodic_time *pt; int i; for(i = 0; i < 3; i++) { printk("*****pit channel %d's state:*****\n", i); - s = &pit->channels[i]; + s = &pit->hw.channels[i]; printk("pit 0x%x.\n", s->count); printk("pit 0x%x.\n", s->latched_count); printk("pit 0x%x.\n", s->count_latched); @@ -379,8 +389,8 @@ static void pit_info(PITState *pit) printk("pit 0x%x.\n", s->gate); printk("pit %"PRId64"\n", s->count_load_time); - if (s->pt) { - struct periodic_time *pt = s->pt; + pt = &pit->pt[i]; + if (pt) { printk("pit channel %d has a periodic timer:\n", i); printk("pt %d.\n", pt->enabled); printk("pt %d.\n", pt->one_shot); @@ -405,131 +415,64 @@ static void pit_save(hvm_domain_context_ { struct domain *d = opaque; PITState *pit = &d->arch.hvm_domain.pl_time.vpit; - PITChannelState *s; - struct periodic_time *pt; - int i, pti = -1; pit_info(pit); - for(i = 0; i < 3; i++) { - s = &pit->channels[i]; - hvm_put_32u(h, s->count); - hvm_put_16u(h, s->latched_count); - hvm_put_8u(h, s->count_latched); - hvm_put_8u(h, s->status_latched); - hvm_put_8u(h, s->status); - hvm_put_8u(h, s->read_state); - hvm_put_8u(h, s->write_state); - hvm_put_8u(h, s->write_latch); - hvm_put_8u(h, s->rw_mode); - hvm_put_8u(h, s->mode); - hvm_put_8u(h, s->bcd); - hvm_put_8u(h, s->gate); - hvm_put_64u(h, s->count_load_time); - - if (s->pt.enabled && pti == -1) - pti = i; - } - - pt = &pit->channels[pti].pt; - - /* save the vcpu for pt */ - hvm_put_32u(h, pt->vcpu->vcpu_id); - - /* save guest time */ - hvm_put_8u(h, pti); - hvm_put_32u(h, pt->pending_intr_nr); - hvm_put_64u(h, pt->last_plt_gtime); - + /* Save the PIT hardware state */ + hvm_put_struct(h, &pit->hw); } static int pit_load(hvm_domain_context_t *h, void *opaque, int version_id) { struct domain *d = opaque; PITState *pit = &d->arch.hvm_domain.pl_time.vpit; - PITChannelState *s; - int i, pti, vcpu_id; - u32 period; + int i; if (version_id != 1) return -EINVAL; + /* Restore the PIT hardware state */ + hvm_get_struct(h, &pit->hw); + + /* Recreate platform timers from hardware state. There will be some + * time jitter here, but the wall-clock will have jumped massively, so + * we hope the guest can handle it. */ + for(i = 0; i < 3; i++) { - s = &pit->channels[i]; - s->count = hvm_get_32u(h); - s->latched_count = hvm_get_16u(h); - s->count_latched = hvm_get_8u(h); - s->status_latched = hvm_get_8u(h); - s->status = hvm_get_8u(h); - s->read_state = hvm_get_8u(h); - s->write_state = hvm_get_8u(h); - s->write_latch = hvm_get_8u(h); - s->rw_mode = hvm_get_8u(h); - s->mode = hvm_get_8u(h); - s->bcd = hvm_get_8u(h); - s->gate = hvm_get_8u(h); - s->count_load_time = hvm_get_64u(h); - } - - vcpu_id = hvm_get_32u(h); - - pti = hvm_get_8u(h); - if ( pti < 0 || pti > 2) { - printk("pit load get a wrong channel %d when HVM resume.\n", pti); - return -EINVAL; - } - - s = &pit->channels[pti]; - period = DIV_ROUND((s->count * 1000000000ULL), PIT_FREQ); - - printk("recreate periodic timer %d in mode %d, freq=%d.\n", pti, s->mode, period); - switch (s->mode) { - case 2: - /* create periodic time */ - create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 0, pit_time_fired, s); - break; - case 1: - /* create one shot time */ - create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 1, pit_time_fired, s); - break; - default: - printk("pit mode %"PRId8" should not use periodic timer!\n", s->mode); - return -EINVAL; - } - s->pt.pending_intr_nr = hvm_get_32u(h); - s->pt.last_plt_gtime = hvm_get_64u(h); + pit_load_count(pit, i, pit_get_count(pit, i)); + pit->pt[i].last_plt_gtime = hvm_get_guest_time(d->vcpu[0]); + } pit_info(pit); - return 0; } static void pit_reset(void *opaque) { PITState *pit = opaque; - PITChannelState *s; + struct hvm_hw_pit_channel *s; int i; for(i = 0;i < 3; i++) { - s = &pit->channels[i]; - destroy_periodic_time(&s->pt); + s = &pit->hw.channels[i]; + destroy_periodic_time(&pit->pt[i]); s->mode = 0xff; /* the init mode */ s->gate = (i != 2); - pit_load_count(s, i, 0); + pit_load_count(pit, i, 0); } } void pit_init(struct vcpu *v, unsigned long cpu_khz) { PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit; - PITChannelState *s; - - s = &pit->channels[0]; - s->pt.vcpu = v; + struct periodic_time *pt; + + pt = &pit->pt[0]; + pt->vcpu = v; /* the timer 0 is connected to an IRQ */ - init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor); - s++; s->pt.vcpu = v; - s++; s->pt.vcpu = v; + init_timer(&pt->timer, pt_timer_fn, pt, v->processor); + pt++; pt->vcpu = v; + pt++; pt->vcpu = v; hvm_register_savevm(v->domain, "xen_hvm_i8254", PIT_BASE, 1, pit_save, pit_load, v->domain); register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io); @@ -546,20 +489,18 @@ void pit_migrate_timers(struct vcpu *v) void pit_migrate_timers(struct vcpu *v) { PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit; - PITChannelState *s; - - s = &pit->channels[0]; - if ( s->pt.vcpu == v && s->pt.enabled ) - migrate_timer(&s->pt.timer, v->processor); + struct periodic_time *pt; + + pt = &pit->pt[0]; + if ( pt->vcpu == v && pt->enabled ) + migrate_timer(&pt->timer, v->processor); } void pit_deinit(struct domain *d) { PITState *pit = &d->arch.hvm_domain.pl_time.vpit; - PITChannelState *s; - - s = &pit->channels[0]; - kill_timer(&s->pt.timer); + + kill_timer(&pit->pt[0].timer); } /* the intercept action for PIT DM retval:0--not handled; 1--handled */ @@ -590,7 +531,7 @@ static void speaker_ioport_write(void *o static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val) { PITState *pit = opaque; - pit->speaker_data_on = (val >> 1) & 1; + pit->hw.speaker_data_on = (val >> 1) & 1; pit_set_gate(pit, 2, val & 1); } @@ -598,10 +539,10 @@ static uint32_t speaker_ioport_read(void { PITState *pit = opaque; int out = pit_get_out(pit, 2, - hvm_get_guest_time(pit->channels[2].pt.vcpu)); + hvm_get_guest_time(pit->pt[2].vcpu)); /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */ unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1; - return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) | + return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) | refresh_clock << 4); } diff -r dcb145f858e3 -r 56228886421d xen/arch/x86/hvm/intercept.c --- a/xen/arch/x86/hvm/intercept.c Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/arch/x86/hvm/intercept.c Sat Jan 20 11:17:38 2007 +0000 @@ -358,6 +358,8 @@ int hvm_load(struct vcpu *v, hvm_domain_ instance_id = hvm_get_32u(h); version_id = hvm_get_32u(h); + printk("HVM S/R Loading \"%s\" instance %#x\n", idstr, instance_id); + rec_len = hvm_get_32u(h); rec_pos = hvm_ctxt_tell(h); diff -r dcb145f858e3 -r 56228886421d xen/arch/x86/hvm/vioapic.c --- a/xen/arch/x86/hvm/vioapic.c Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/arch/x86/hvm/vioapic.c Sat Jan 20 11:17:38 2007 +0000 @@ -312,7 +312,7 @@ static inline int pit_channel0_enabled(v static inline int pit_channel0_enabled(void) { PITState *pit = ¤t->domain->arch.hvm_domain.pl_time.vpit; - struct periodic_time *pt = &pit->channels[0].pt; + struct periodic_time *pt = &pit->pt[0]; return pt->enabled; } diff -r dcb145f858e3 -r 56228886421d xen/include/asm-x86/hvm/support.h --- a/xen/include/asm-x86/hvm/support.h Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/include/asm-x86/hvm/support.h Sat Jan 20 11:17:38 2007 +0000 @@ -186,7 +186,6 @@ static inline void hvm_put_buffer(hvm_do h->cur += len; } - static inline char hvm_get_byte(hvm_domain_context_t *h) { if (h->cur >= HVM_CTXT_SIZE) { @@ -239,6 +238,12 @@ static inline void hvm_get_buffer(hvm_do memcpy(buf, &h->data[h->cur], len); h->cur += len; } + +#define hvm_put_struct(_h, _p) \ + hvm_put_buffer((_h), (char *)(_p), sizeof(*(_p))) +#define hvm_get_struct(_h, _p) \ + hvm_get_buffer((_h), (char *)(_p), sizeof(*(_p))) + extern int hvm_save(struct vcpu*, hvm_domain_context_t *h); extern int hvm_load(struct vcpu*, hvm_domain_context_t *h); diff -r dcb145f858e3 -r 56228886421d xen/include/asm-x86/hvm/vpt.h --- a/xen/include/asm-x86/hvm/vpt.h Fri Jan 19 15:23:41 2007 +0000 +++ b/xen/include/asm-x86/hvm/vpt.h Sat Jan 20 11:17:38 2007 +0000 @@ -29,7 +29,7 @@ #include <xen/timer.h> #include <xen/list.h> #include <asm/hvm/vpic.h> - +#include <public/hvm/save.h> #define HPET_TIMER_NUM 3 /* 3 timers supported now */ struct HPET { @@ -90,27 +90,11 @@ struct periodic_time { #define PIT_FREQ 1193181 #define PIT_BASE 0x40 -typedef struct PITChannelState { - int count; /* can be 65536 */ - u16 latched_count; - u8 count_latched; - u8 status_latched; - u8 status; - u8 read_state; - u8 write_state; - u8 write_latch; - u8 rw_mode; - u8 mode; - u8 bcd; /* not supported */ - u8 gate; /* timer start */ - s64 count_load_time; +typedef struct PITState { + /* Hardware state */ + struct hvm_hw_pit hw; /* irq handling */ - struct periodic_time pt; -} PITChannelState; - -typedef struct PITState { - PITChannelState channels[3]; - int speaker_data_on; + struct periodic_time pt[3]; } PITState; #define RTC_SIZE 14 diff -r dcb145f858e3 -r 56228886421d xen/include/public/hvm/save.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/xen/include/public/hvm/save.h Sat Jan 20 11:17:38 2007 +0000 @@ -0,0 +1,138 @@ +/* + * hvm/save.h + * + * Structure definitions for HVM state that is held by Xen and must + * be saved along with the domain's memory and device-model state. + * + * + * Copyright (c) 2007 XenSource Ltd. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __XEN_PUBLIC_HVM_SAVE_H__ +#define __XEN_PUBLIC_HVM_SAVE_H__ + +/* + * Structures in this header *must* have the same layout in 32bit + * and 64bit environments: this means that all fields must be explicitly + * sized types and aligned to their sizes. + * + * Only the state necessary for saving and restoring (i.e. fields + * that are analogous to actual hardware state) should go in this file. + * Internal mechanisms should be kept in Xen-private headers. + */ + + + +/* + * Processor + */ +#define HVM_SAVE_TYPE_CPU 1 +struct hvm_hw_cpu { + uint64_t eip; + uint64_t esp; + uint64_t eflags; + uint64_t cr0; + uint64_t cr3; + uint64_t cr4; + + uint32_t cs_sel; + uint32_t ds_sel; + uint32_t es_sel; + uint32_t fs_sel; + uint32_t gs_sel; + uint32_t ss_sel; + uint32_t tr_sel; + uint32_t ldtr_sel; + + uint32_t cs_limit; + uint32_t ds_limit; + uint32_t es_limit; + uint32_t fs_limit; + uint32_t gs_limit; + uint32_t ss_limit; + uint32_t tr_limit; + uint32_t ldtr_limit; + uint32_t idtr_limit; + uint32_t gdtr_limit; + + uint64_t cs_base; + uint64_t ds_base; + uint64_t es_base; + uint64_t fs_base; + uint64_t gs_base; + uint64_t ss_base; + uint64_t tr_base; + uint64_t ldtr_base; + uint64_t idtr_base; + uint64_t gdtr_base; + + + uint32_t cs_arbytes; + uint32_t ds_arbytes; + uint32_t es_arbytes; + uint32_t fs_arbytes; + uint32_t gs_arbytes; + uint32_t ss_arbytes; + uint32_t tr_arbytes; + uint32_t ldtr_arbytes; + + uint32_t sysenter_cs; + uint32_t padding0; + + uint64_t sysenter_esp; + uint64_t sysenter_eip; + + /* msr for em64t */ + uint64_t shadow_gs; + uint64_t flags; + + /* same size as VMX_MSR_COUNT */ + uint64_t msr_items[6]; + uint64_t vmxassist_enabled; +}; + + +/* + * PIT + */ +#define HVM_SAVE_TYPE_PIT 2 +struct hvm_hw_pit { + struct hvm_hw_pit_channel { + int64_t count_load_time; + uint32_t count; /* can be 65536 */ + uint16_t latched_count; + uint8_t count_latched; + uint8_t status_latched; + uint8_t status; + uint8_t read_state; + uint8_t write_state; + uint8_t write_latch; + uint8_t rw_mode; + uint8_t mode; + uint8_t bcd; /* not supported */ + uint8_t gate; /* timer start */ + } channels[3]; /* 3 x 24 bytes */ + uint32_t speaker_data_on; +}; + + + +#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |