ia64/xen-unstable

changeset 13541:56228886421d

[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@xensource.com>
author Tim Deegan <Tim.Deegan@xensource.com>
date Sat Jan 20 11:17:38 2007 +0000 (2007-01-20)
parents dcb145f858e3
children dccdc3ee0efc
files xen/arch/x86/domain.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/vioapic.c xen/include/asm-x86/hvm/support.h xen/include/asm-x86/hvm/vpt.h xen/include/public/hvm/save.h
line diff
     1.1 --- a/xen/arch/x86/domain.c	Fri Jan 19 15:23:41 2007 +0000
     1.2 +++ b/xen/arch/x86/domain.c	Sat Jan 20 11:17:38 2007 +0000
     1.3 @@ -329,9 +329,6 @@ int vcpu_initialise(struct vcpu *v)
     1.4  
     1.5      pae_l3_cache_init(&v->arch.pae_l3_cache);
     1.6  
     1.7 -    /* This should move to arch_domain_create(). */
     1.8 -    if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
     1.9 -        pit_init(v, cpu_khz);
    1.10  
    1.11      if ( is_hvm_domain(d) )
    1.12      {
    1.13 @@ -340,6 +337,10 @@ int vcpu_initialise(struct vcpu *v)
    1.14      }
    1.15      else
    1.16      {
    1.17 +        /* PV guests get an emulated PIT too for video BIOSes to use. */
    1.18 +        if ( !is_idle_domain(d) && (v->vcpu_id == 0) )
    1.19 +            pit_init(v, cpu_khz);
    1.20 +
    1.21          v->arch.schedule_tail = continue_nonidle_domain;
    1.22          v->arch.ctxt_switch_from = paravirt_ctxt_switch_from;
    1.23          v->arch.ctxt_switch_to   = paravirt_ctxt_switch_to;
     2.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Jan 19 15:23:41 2007 +0000
     2.2 +++ b/xen/arch/x86/hvm/hvm.c	Sat Jan 20 11:17:38 2007 +0000
     2.3 @@ -194,6 +194,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
     2.4      if ( v->vcpu_id != 0 )
     2.5          return 0;
     2.6  
     2.7 +    pit_init(v, cpu_khz);
     2.8      rtc_init(v, RTC_PORT(0), RTC_IRQ);
     2.9      pmtimer_init(v, ACPI_PM_TMR_BLK_ADDRESS);
    2.10      hpet_init(v);
     3.1 --- a/xen/arch/x86/hvm/i8254.c	Fri Jan 19 15:23:41 2007 +0000
     3.2 +++ b/xen/arch/x86/hvm/i8254.c	Sat Jan 20 11:17:38 2007 +0000
     3.3 @@ -76,37 +76,42 @@ uint64_t muldiv64(uint64_t a, uint32_t b
     3.4      return res.ll;
     3.5  }
     3.6  
     3.7 -static int pit_get_count(PITChannelState *s)
     3.8 +static int pit_get_count(PITState *s, int channel)
     3.9  {
    3.10      uint64_t d;
    3.11      int  counter;
    3.12 +    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
    3.13 +    struct periodic_time *pt = &s->pt[channel];
    3.14  
    3.15 -    d = muldiv64(hvm_get_guest_time(s->pt.vcpu) - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
    3.16 -    switch(s->mode) {
    3.17 +    d = muldiv64(hvm_get_guest_time(pt->vcpu) 
    3.18 +                 - c->count_load_time, PIT_FREQ, ticks_per_sec(pt->vcpu));
    3.19 +    switch(c->mode) {
    3.20      case 0:
    3.21      case 1:
    3.22      case 4:
    3.23      case 5:
    3.24 -        counter = (s->count - d) & 0xffff;
    3.25 +        counter = (c->count - d) & 0xffff;
    3.26          break;
    3.27      case 3:
    3.28          /* XXX: may be incorrect for odd counts */
    3.29 -        counter = s->count - ((2 * d) % s->count);
    3.30 +        counter = c->count - ((2 * d) % c->count);
    3.31          break;
    3.32      default:
    3.33 -        counter = s->count - (d % s->count);
    3.34 +        counter = c->count - (d % c->count);
    3.35          break;
    3.36      }
    3.37      return counter;
    3.38  }
    3.39  
    3.40  /* get pit output bit */
    3.41 -static int pit_get_out1(PITChannelState *s, int64_t current_time)
    3.42 +int pit_get_out(PITState *pit, int channel, int64_t current_time)
    3.43  {
    3.44 +    struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
    3.45      uint64_t d;
    3.46      int out;
    3.47  
    3.48 -    d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec(s->pt.vcpu));
    3.49 +    d = muldiv64(current_time - s->count_load_time, 
    3.50 +                 PIT_FREQ, ticks_per_sec(pit->pt[channel].vcpu));
    3.51      switch(s->mode) {
    3.52      default:
    3.53      case 0:
    3.54 @@ -132,16 +137,11 @@ static int pit_get_out1(PITChannelState 
    3.55      return out;
    3.56  }
    3.57  
    3.58 -int pit_get_out(PITState *pit, int channel, int64_t current_time)
    3.59 -{
    3.60 -    PITChannelState *s = &pit->channels[channel];
    3.61 -    return pit_get_out1(s, current_time);
    3.62 -}
    3.63 -
    3.64  /* val must be 0 or 1 */
    3.65  void pit_set_gate(PITState *pit, int channel, int val)
    3.66  {
    3.67 -    PITChannelState *s = &pit->channels[channel];
    3.68 +    struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
    3.69 +    struct periodic_time *pt = &pit->pt[channel];
    3.70  
    3.71      switch(s->mode) {
    3.72      default:
    3.73 @@ -153,7 +153,7 @@ void pit_set_gate(PITState *pit, int cha
    3.74      case 5:
    3.75          if (s->gate < val) {
    3.76              /* restart counting on rising edge */
    3.77 -            s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
    3.78 +            s->count_load_time = hvm_get_guest_time(pt->vcpu);
    3.79  //            pit_irq_timer_update(s, s->count_load_time);
    3.80          }
    3.81          break;
    3.82 @@ -161,7 +161,7 @@ void pit_set_gate(PITState *pit, int cha
    3.83      case 3:
    3.84          if (s->gate < val) {
    3.85              /* restart counting on rising edge */
    3.86 -            s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
    3.87 +            s->count_load_time = hvm_get_guest_time(pt->vcpu);
    3.88  //            pit_irq_timer_update(s, s->count_load_time);
    3.89          }
    3.90          /* XXX: disable/enable counting */
    3.91 @@ -172,23 +172,25 @@ void pit_set_gate(PITState *pit, int cha
    3.92  
    3.93  int pit_get_gate(PITState *pit, int channel)
    3.94  {
    3.95 -    PITChannelState *s = &pit->channels[channel];
    3.96 -    return s->gate;
    3.97 +    return pit->hw.channels[channel].gate;
    3.98  }
    3.99  
   3.100  void pit_time_fired(struct vcpu *v, void *priv)
   3.101  {
   3.102 -    PITChannelState *s = priv;
   3.103 +    struct hvm_hw_pit_channel *s = priv;
   3.104      s->count_load_time = hvm_get_guest_time(v);
   3.105  }
   3.106  
   3.107 -static inline void pit_load_count(PITChannelState *s, int channel, int val)
   3.108 +static inline void pit_load_count(PITState *pit, int channel, int val)
   3.109  {
   3.110      u32 period;
   3.111 +    struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
   3.112 +    struct periodic_time *pt = &pit->pt[channel];
   3.113 +    struct vcpu *v;
   3.114  
   3.115      if (val == 0)
   3.116          val = 0x10000;
   3.117 -    s->count_load_time = hvm_get_guest_time(s->pt.vcpu);
   3.118 +    s->count_load_time = hvm_get_guest_time(pt->vcpu);
   3.119      s->count = val;
   3.120      period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
   3.121  
   3.122 @@ -204,30 +206,38 @@ static inline void pit_load_count(PITCha
   3.123              (long long)s->count_load_time);
   3.124  #endif
   3.125  
   3.126 +    /* Choose a vcpu to set the timer on: current if appropriate else vcpu 0 */
   3.127 +    if ( likely(pit == &current->domain->arch.hvm_domain.pl_time.vpit) )
   3.128 +        v = current;
   3.129 +    else 
   3.130 +        v = container_of(pit, struct domain, 
   3.131 +                         arch.hvm_domain.pl_time.vpit)->vcpu[0];
   3.132 +
   3.133      switch (s->mode) {
   3.134          case 2:
   3.135              /* create periodic time */
   3.136 -            create_periodic_time(current, &s->pt, period, 0, 0, pit_time_fired, s);
   3.137 +            create_periodic_time(v, pt, period, 0, 0, pit_time_fired, s);
   3.138              break;
   3.139          case 1:
   3.140              /* create one shot time */
   3.141 -            create_periodic_time(current, &s->pt, period, 0, 1, pit_time_fired, s);
   3.142 +            create_periodic_time(v, pt, period, 0, 1, pit_time_fired, s);
   3.143  #ifdef DEBUG_PIT
   3.144              printk("HVM_PIT: create one shot time.\n");
   3.145  #endif
   3.146              break;
   3.147          default:
   3.148 -            destroy_periodic_time(&s->pt);
   3.149 +            destroy_periodic_time(pt);
   3.150              break;
   3.151      }
   3.152  }
   3.153  
   3.154  /* if already latched, do not latch again */
   3.155 -static void pit_latch_count(PITChannelState *s)
   3.156 +static void pit_latch_count(PITState *s, int channel)
   3.157  {
   3.158 -    if (!s->count_latched) {
   3.159 -        s->latched_count = pit_get_count(s);
   3.160 -        s->count_latched = s->rw_mode;
   3.161 +    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
   3.162 +    if (!c->count_latched) {
   3.163 +        c->latched_count = pit_get_count(s, channel);
   3.164 +        c->count_latched = c->rw_mode;
   3.165      }
   3.166  }
   3.167  
   3.168 @@ -235,7 +245,7 @@ static void pit_ioport_write(void *opaqu
   3.169  {
   3.170      PITState *pit = opaque;
   3.171      int channel, access;
   3.172 -    PITChannelState *s;
   3.173 +    struct hvm_hw_pit_channel *s;
   3.174      val &= 0xff;
   3.175  
   3.176      addr &= 3;
   3.177 @@ -244,15 +254,15 @@ static void pit_ioport_write(void *opaqu
   3.178          if (channel == 3) {
   3.179              /* read back command */
   3.180              for(channel = 0; channel < 3; channel++) {
   3.181 -                s = &pit->channels[channel];
   3.182 +                s = &pit->hw.channels[channel];
   3.183                  if (val & (2 << channel)) {
   3.184                      if (!(val & 0x20)) {
   3.185 -                        pit_latch_count(s);
   3.186 +                        pit_latch_count(pit, channel);
   3.187                      }
   3.188                      if (!(val & 0x10) && !s->status_latched) {
   3.189                          /* status latch */
   3.190                          /* XXX: add BCD and null count */
   3.191 -                        s->status =  (pit_get_out1(s, hvm_get_guest_time(s->pt.vcpu)) << 7) |
   3.192 +                        s->status = (pit_get_out(pit, channel, hvm_get_guest_time(pit->pt[channel].vcpu)) << 7) |
   3.193                              (s->rw_mode << 4) |
   3.194                              (s->mode << 1) |
   3.195                              s->bcd;
   3.196 @@ -261,10 +271,10 @@ static void pit_ioport_write(void *opaqu
   3.197                  }
   3.198              }
   3.199          } else {
   3.200 -            s = &pit->channels[channel];
   3.201 +            s = &pit->hw.channels[channel];
   3.202              access = (val >> 4) & 3;
   3.203              if (access == 0) {
   3.204 -                pit_latch_count(s);
   3.205 +                pit_latch_count(pit, channel);
   3.206              } else {
   3.207                  s->rw_mode = access;
   3.208                  s->read_state = access;
   3.209 @@ -276,21 +286,21 @@ static void pit_ioport_write(void *opaqu
   3.210              }
   3.211          }
   3.212      } else {
   3.213 -        s = &pit->channels[addr];
   3.214 +        s = &pit->hw.channels[addr];
   3.215          switch(s->write_state) {
   3.216          default:
   3.217          case RW_STATE_LSB:
   3.218 -            pit_load_count(s, addr, val);
   3.219 +            pit_load_count(pit, addr, val);
   3.220              break;
   3.221          case RW_STATE_MSB:
   3.222 -            pit_load_count(s, addr, val << 8);
   3.223 +            pit_load_count(pit, addr, val << 8);
   3.224              break;
   3.225          case RW_STATE_WORD0:
   3.226              s->write_latch = val;
   3.227              s->write_state = RW_STATE_WORD1;
   3.228              break;
   3.229          case RW_STATE_WORD1:
   3.230 -            pit_load_count(s, addr, s->write_latch | (val << 8));
   3.231 +            pit_load_count(pit, addr, s->write_latch | (val << 8));
   3.232              s->write_state = RW_STATE_WORD0;
   3.233              break;
   3.234          }
   3.235 @@ -301,10 +311,10 @@ static uint32_t pit_ioport_read(void *op
   3.236  {
   3.237      PITState *pit = opaque;
   3.238      int ret, count;
   3.239 -    PITChannelState *s;
   3.240 +    struct hvm_hw_pit_channel *s;
   3.241      
   3.242      addr &= 3;
   3.243 -    s = &pit->channels[addr];
   3.244 +    s = &pit->hw.channels[addr];
   3.245      if (s->status_latched) {
   3.246          s->status_latched = 0;
   3.247          ret = s->status;
   3.248 @@ -328,20 +338,20 @@ static uint32_t pit_ioport_read(void *op
   3.249          switch(s->read_state) {
   3.250          default:
   3.251          case RW_STATE_LSB:
   3.252 -            count = pit_get_count(s);
   3.253 +            count = pit_get_count(pit, addr);
   3.254              ret = count & 0xff;
   3.255              break;
   3.256          case RW_STATE_MSB:
   3.257 -            count = pit_get_count(s);
   3.258 +            count = pit_get_count(pit, addr);
   3.259              ret = (count >> 8) & 0xff;
   3.260              break;
   3.261          case RW_STATE_WORD0:
   3.262 -            count = pit_get_count(s);
   3.263 +            count = pit_get_count(pit, addr);
   3.264              ret = count & 0xff;
   3.265              s->read_state = RW_STATE_WORD1;
   3.266              break;
   3.267          case RW_STATE_WORD1:
   3.268 -            count = pit_get_count(s);
   3.269 +            count = pit_get_count(pit, addr);
   3.270              ret = (count >> 8) & 0xff;
   3.271              s->read_state = RW_STATE_WORD0;
   3.272              break;
   3.273 @@ -352,19 +362,19 @@ static uint32_t pit_ioport_read(void *op
   3.274  
   3.275  void pit_stop_channel0_irq(PITState * pit)
   3.276  {
   3.277 -    PITChannelState *s = &pit->channels[0];
   3.278 -    destroy_periodic_time(&s->pt);
   3.279 +    destroy_periodic_time(&pit->pt[0]);
   3.280  }
   3.281  
   3.282  #ifdef HVM_DEBUG_SUSPEND
   3.283  static void pit_info(PITState *pit)
   3.284  {
   3.285 -    PITChannelState *s;
   3.286 +    struct hvm_hw_pit_channel *s;
   3.287 +    struct periodic_time *pt;
   3.288      int i;
   3.289  
   3.290      for(i = 0; i < 3; i++) {
   3.291          printk("*****pit channel %d's state:*****\n", i);
   3.292 -        s = &pit->channels[i];
   3.293 +        s = &pit->hw.channels[i];
   3.294          printk("pit 0x%x.\n", s->count);
   3.295          printk("pit 0x%x.\n", s->latched_count);
   3.296          printk("pit 0x%x.\n", s->count_latched);
   3.297 @@ -379,8 +389,8 @@ static void pit_info(PITState *pit)
   3.298          printk("pit 0x%x.\n", s->gate);
   3.299          printk("pit %"PRId64"\n", s->count_load_time);
   3.300  
   3.301 -        if (s->pt) {
   3.302 -            struct periodic_time *pt = s->pt;
   3.303 +        pt = &pit->pt[i];
   3.304 +        if (pt) {
   3.305              printk("pit channel %d has a periodic timer:\n", i);
   3.306              printk("pt %d.\n", pt->enabled);
   3.307              printk("pt %d.\n", pt->one_shot);
   3.308 @@ -405,131 +415,64 @@ static void pit_save(hvm_domain_context_
   3.309  {
   3.310      struct domain *d = opaque;
   3.311      PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
   3.312 -    PITChannelState *s;
   3.313 -    struct periodic_time *pt;
   3.314 -    int i, pti = -1;
   3.315      
   3.316      pit_info(pit);
   3.317  
   3.318 -    for(i = 0; i < 3; i++) {
   3.319 -        s = &pit->channels[i];
   3.320 -        hvm_put_32u(h, s->count);
   3.321 -        hvm_put_16u(h, s->latched_count);
   3.322 -        hvm_put_8u(h, s->count_latched);
   3.323 -        hvm_put_8u(h, s->status_latched);
   3.324 -        hvm_put_8u(h, s->status);
   3.325 -        hvm_put_8u(h, s->read_state);
   3.326 -        hvm_put_8u(h, s->write_state);
   3.327 -        hvm_put_8u(h, s->write_latch);
   3.328 -        hvm_put_8u(h, s->rw_mode);
   3.329 -        hvm_put_8u(h, s->mode);
   3.330 -        hvm_put_8u(h, s->bcd);
   3.331 -        hvm_put_8u(h, s->gate);
   3.332 -        hvm_put_64u(h, s->count_load_time);
   3.333 -
   3.334 -        if (s->pt.enabled && pti == -1)
   3.335 -            pti = i;
   3.336 -    }
   3.337 -
   3.338 -    pt = &pit->channels[pti].pt;
   3.339 -
   3.340 -    /* save the vcpu for pt */
   3.341 -    hvm_put_32u(h, pt->vcpu->vcpu_id);
   3.342 -
   3.343 -    /* save guest time */
   3.344 -    hvm_put_8u(h, pti);
   3.345 -    hvm_put_32u(h, pt->pending_intr_nr);
   3.346 -    hvm_put_64u(h, pt->last_plt_gtime);
   3.347 -
   3.348 +    /* Save the PIT hardware state */
   3.349 +    hvm_put_struct(h, &pit->hw);
   3.350  }
   3.351  
   3.352  static int pit_load(hvm_domain_context_t *h, void *opaque, int version_id)
   3.353  {
   3.354      struct domain *d = opaque;
   3.355      PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
   3.356 -    PITChannelState *s;
   3.357 -    int i, pti, vcpu_id;
   3.358 -    u32 period;
   3.359 +    int i;
   3.360  
   3.361      if (version_id != 1)
   3.362          return -EINVAL;
   3.363  
   3.364 +    /* Restore the PIT hardware state */
   3.365 +    hvm_get_struct(h, &pit->hw);
   3.366 +    
   3.367 +    /* Recreate platform timers from hardware state.  There will be some 
   3.368 +     * time jitter here, but the wall-clock will have jumped massively, so 
   3.369 +     * we hope the guest can handle it. */
   3.370 +
   3.371      for(i = 0; i < 3; i++) {
   3.372 -        s = &pit->channels[i];
   3.373 -        s->count = hvm_get_32u(h);
   3.374 -        s->latched_count = hvm_get_16u(h);
   3.375 -        s->count_latched = hvm_get_8u(h);
   3.376 -        s->status_latched = hvm_get_8u(h);
   3.377 -        s->status = hvm_get_8u(h);
   3.378 -        s->read_state = hvm_get_8u(h);
   3.379 -        s->write_state = hvm_get_8u(h);
   3.380 -        s->write_latch = hvm_get_8u(h);
   3.381 -        s->rw_mode = hvm_get_8u(h);
   3.382 -        s->mode = hvm_get_8u(h);
   3.383 -        s->bcd = hvm_get_8u(h);
   3.384 -        s->gate = hvm_get_8u(h);
   3.385 -        s->count_load_time = hvm_get_64u(h);
   3.386 +        pit_load_count(pit, i, pit_get_count(pit, i));
   3.387 +        pit->pt[i].last_plt_gtime = hvm_get_guest_time(d->vcpu[0]);
   3.388      }
   3.389  
   3.390 -    vcpu_id = hvm_get_32u(h);
   3.391 -
   3.392 -    pti = hvm_get_8u(h);
   3.393 -    if ( pti < 0 || pti > 2) {
   3.394 -        printk("pit load get a wrong channel %d when HVM resume.\n", pti);
   3.395 -        return -EINVAL;
   3.396 -    }
   3.397 -
   3.398 -    s = &pit->channels[pti];
   3.399 -    period = DIV_ROUND((s->count * 1000000000ULL), PIT_FREQ);
   3.400 -
   3.401 -    printk("recreate periodic timer %d in mode %d, freq=%d.\n", pti, s->mode, period);
   3.402 -    switch (s->mode) {
   3.403 -        case 2:
   3.404 -            /* create periodic time */
   3.405 -            create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 0, pit_time_fired, s);
   3.406 -            break;
   3.407 -        case 1:
   3.408 -            /* create one shot time */
   3.409 -            create_periodic_time(d->vcpu[vcpu_id], &s->pt, period, 0, 1, pit_time_fired, s);
   3.410 -            break;
   3.411 -        default:
   3.412 -            printk("pit mode %"PRId8" should not use periodic timer!\n", s->mode);
   3.413 -            return -EINVAL;
   3.414 -    }
   3.415 -    s->pt.pending_intr_nr = hvm_get_32u(h);
   3.416 -    s->pt.last_plt_gtime = hvm_get_64u(h);
   3.417 -
   3.418      pit_info(pit);
   3.419 -
   3.420      return 0;
   3.421  }
   3.422  
   3.423  static void pit_reset(void *opaque)
   3.424  {
   3.425      PITState *pit = opaque;
   3.426 -    PITChannelState *s;
   3.427 +    struct hvm_hw_pit_channel *s;
   3.428      int i;
   3.429  
   3.430      for(i = 0;i < 3; i++) {
   3.431 -        s = &pit->channels[i];
   3.432 -        destroy_periodic_time(&s->pt);
   3.433 +        s = &pit->hw.channels[i];
   3.434 +        destroy_periodic_time(&pit->pt[i]);
   3.435          s->mode = 0xff; /* the init mode */
   3.436          s->gate = (i != 2);
   3.437 -        pit_load_count(s, i, 0);
   3.438 +        pit_load_count(pit, i, 0);
   3.439      }
   3.440  }
   3.441  
   3.442  void pit_init(struct vcpu *v, unsigned long cpu_khz)
   3.443  {
   3.444      PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
   3.445 -    PITChannelState *s;
   3.446 +    struct periodic_time *pt;
   3.447  
   3.448 -    s = &pit->channels[0];
   3.449 -    s->pt.vcpu = v;
   3.450 +    pt = &pit->pt[0];  
   3.451 +    pt->vcpu = v;
   3.452      /* the timer 0 is connected to an IRQ */
   3.453 -    init_timer(&s->pt.timer, pt_timer_fn, &s->pt, v->processor);
   3.454 -    s++; s->pt.vcpu = v;
   3.455 -    s++; s->pt.vcpu = v;
   3.456 +    init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
   3.457 +    pt++; pt->vcpu = v;
   3.458 +    pt++; pt->vcpu = v;
   3.459  
   3.460      hvm_register_savevm(v->domain, "xen_hvm_i8254", PIT_BASE, 1, pit_save, pit_load, v->domain);
   3.461      register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
   3.462 @@ -546,20 +489,18 @@ void pit_init(struct vcpu *v, unsigned l
   3.463  void pit_migrate_timers(struct vcpu *v)
   3.464  {
   3.465      PITState *pit = &v->domain->arch.hvm_domain.pl_time.vpit;
   3.466 -    PITChannelState *s;
   3.467 +    struct periodic_time *pt;
   3.468  
   3.469 -    s = &pit->channels[0];
   3.470 -    if ( s->pt.vcpu == v && s->pt.enabled )
   3.471 -        migrate_timer(&s->pt.timer, v->processor);
   3.472 +    pt = &pit->pt[0];
   3.473 +    if ( pt->vcpu == v && pt->enabled )
   3.474 +        migrate_timer(&pt->timer, v->processor);
   3.475  }
   3.476  
   3.477  void pit_deinit(struct domain *d)
   3.478  {
   3.479      PITState *pit = &d->arch.hvm_domain.pl_time.vpit;
   3.480 -    PITChannelState *s;
   3.481  
   3.482 -    s = &pit->channels[0];
   3.483 -    kill_timer(&s->pt.timer);
   3.484 +    kill_timer(&pit->pt[0].timer);
   3.485  }
   3.486  
   3.487  /* the intercept action for PIT DM retval:0--not handled; 1--handled */  
   3.488 @@ -590,7 +531,7 @@ static int handle_pit_io(ioreq_t *p)
   3.489  static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
   3.490  {
   3.491      PITState *pit = opaque;
   3.492 -    pit->speaker_data_on = (val >> 1) & 1;
   3.493 +    pit->hw.speaker_data_on = (val >> 1) & 1;
   3.494      pit_set_gate(pit, 2, val & 1);
   3.495  }
   3.496  
   3.497 @@ -598,10 +539,10 @@ static uint32_t speaker_ioport_read(void
   3.498  {
   3.499      PITState *pit = opaque;
   3.500      int out = pit_get_out(pit, 2,
   3.501 -                          hvm_get_guest_time(pit->channels[2].pt.vcpu));
   3.502 +                          hvm_get_guest_time(pit->pt[2].vcpu));
   3.503      /* Refresh clock toggles at about 15us. We approximate as 2^14ns. */
   3.504      unsigned int refresh_clock = ((unsigned int)NOW() >> 14) & 1;
   3.505 -    return ((pit->speaker_data_on << 1) | pit_get_gate(pit, 2) |
   3.506 +    return ((pit->hw.speaker_data_on << 1) | pit_get_gate(pit, 2) |
   3.507              (out << 5) | refresh_clock << 4);
   3.508  }
   3.509  
     4.1 --- a/xen/arch/x86/hvm/intercept.c	Fri Jan 19 15:23:41 2007 +0000
     4.2 +++ b/xen/arch/x86/hvm/intercept.c	Sat Jan 20 11:17:38 2007 +0000
     4.3 @@ -358,6 +358,8 @@ int hvm_load(struct vcpu *v, hvm_domain_
     4.4          instance_id = hvm_get_32u(h);
     4.5          version_id = hvm_get_32u(h);
     4.6  
     4.7 +        printk("HVM S/R Loading \"%s\" instance %#x\n", idstr, instance_id);
     4.8 +
     4.9          rec_len = hvm_get_32u(h);
    4.10          rec_pos = hvm_ctxt_tell(h);
    4.11  
     5.1 --- a/xen/arch/x86/hvm/vioapic.c	Fri Jan 19 15:23:41 2007 +0000
     5.2 +++ b/xen/arch/x86/hvm/vioapic.c	Sat Jan 20 11:17:38 2007 +0000
     5.3 @@ -312,7 +312,7 @@ static uint32_t ioapic_get_delivery_bitm
     5.4  static inline int pit_channel0_enabled(void)
     5.5  {
     5.6      PITState *pit = &current->domain->arch.hvm_domain.pl_time.vpit;
     5.7 -    struct periodic_time *pt = &pit->channels[0].pt;
     5.8 +    struct periodic_time *pt = &pit->pt[0];
     5.9      return pt->enabled;
    5.10  }
    5.11  
     6.1 --- a/xen/include/asm-x86/hvm/support.h	Fri Jan 19 15:23:41 2007 +0000
     6.2 +++ b/xen/include/asm-x86/hvm/support.h	Sat Jan 20 11:17:38 2007 +0000
     6.3 @@ -186,7 +186,6 @@ static inline void hvm_put_buffer(hvm_do
     6.4      h->cur += len;
     6.5  }
     6.6  
     6.7 -
     6.8  static inline char hvm_get_byte(hvm_domain_context_t *h)
     6.9  {
    6.10      if (h->cur >= HVM_CTXT_SIZE) {
    6.11 @@ -240,6 +239,12 @@ static inline void hvm_get_buffer(hvm_do
    6.12      h->cur += len;
    6.13  }
    6.14  
    6.15 +#define hvm_put_struct(_h, _p) \
    6.16 +    hvm_put_buffer((_h), (char *)(_p), sizeof(*(_p)))
    6.17 +#define hvm_get_struct(_h, _p) \
    6.18 +    hvm_get_buffer((_h), (char *)(_p), sizeof(*(_p)))
    6.19 +
    6.20 +
    6.21  extern int hvm_save(struct vcpu*, hvm_domain_context_t *h);
    6.22  extern int hvm_load(struct vcpu*, hvm_domain_context_t *h);
    6.23  
     7.1 --- a/xen/include/asm-x86/hvm/vpt.h	Fri Jan 19 15:23:41 2007 +0000
     7.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Sat Jan 20 11:17:38 2007 +0000
     7.3 @@ -29,7 +29,7 @@
     7.4  #include <xen/timer.h>
     7.5  #include <xen/list.h>
     7.6  #include <asm/hvm/vpic.h>
     7.7 -
     7.8 +#include <public/hvm/save.h>
     7.9  
    7.10  #define HPET_TIMER_NUM     3    /* 3 timers supported now */
    7.11  struct HPET {
    7.12 @@ -90,27 +90,11 @@ struct periodic_time {
    7.13  #define PIT_FREQ 1193181
    7.14  #define PIT_BASE 0x40
    7.15  
    7.16 -typedef struct PITChannelState {
    7.17 -    int count; /* can be 65536 */
    7.18 -    u16 latched_count;
    7.19 -    u8 count_latched;
    7.20 -    u8 status_latched;
    7.21 -    u8 status;
    7.22 -    u8 read_state;
    7.23 -    u8 write_state;
    7.24 -    u8 write_latch;
    7.25 -    u8 rw_mode;
    7.26 -    u8 mode;
    7.27 -    u8 bcd; /* not supported */
    7.28 -    u8 gate; /* timer start */
    7.29 -    s64 count_load_time;
    7.30 +typedef struct PITState {
    7.31 +    /* Hardware state */
    7.32 +    struct hvm_hw_pit hw;
    7.33      /* irq handling */
    7.34 -    struct periodic_time pt;
    7.35 -} PITChannelState;
    7.36 -
    7.37 -typedef struct PITState {
    7.38 -    PITChannelState channels[3];
    7.39 -    int speaker_data_on;
    7.40 +    struct periodic_time pt[3];
    7.41  } PITState;
    7.42  
    7.43  #define RTC_SIZE 14
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen/include/public/hvm/save.h	Sat Jan 20 11:17:38 2007 +0000
     8.3 @@ -0,0 +1,138 @@
     8.4 +/* 
     8.5 + * hvm/save.h
     8.6 + *
     8.7 + * Structure definitions for HVM state that is held by Xen and must
     8.8 + * be saved along with the domain's memory and device-model state.
     8.9 + *
    8.10 + * 
    8.11 + * Copyright (c) 2007 XenSource Ltd.
    8.12 + *
    8.13 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.14 + * of this software and associated documentation files (the "Software"), to
    8.15 + * deal in the Software without restriction, including without limitation the
    8.16 + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
    8.17 + * sell copies of the Software, and to permit persons to whom the Software is
    8.18 + * furnished to do so, subject to the following conditions:
    8.19 + *
    8.20 + * The above copyright notice and this permission notice shall be included in
    8.21 + * all copies or substantial portions of the Software.
    8.22 + *
    8.23 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.24 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.25 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    8.26 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.27 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    8.28 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    8.29 + * DEALINGS IN THE SOFTWARE.
    8.30 + */
    8.31 +
    8.32 +#ifndef __XEN_PUBLIC_HVM_SAVE_H__
    8.33 +#define __XEN_PUBLIC_HVM_SAVE_H__
    8.34 +
    8.35 +/*
    8.36 + * Structures in this header *must* have the same layout in 32bit 
    8.37 + * and 64bit environments: this means that all fields must be explicitly 
    8.38 + * sized types and aligned to their sizes.
    8.39 + *
    8.40 + * Only the state necessary for saving and restoring (i.e. fields 
    8.41 + * that are analogous to actual hardware state) should go in this file. 
    8.42 + * Internal mechanisms should be kept in Xen-private headers.
    8.43 + */
    8.44 +
    8.45 +
    8.46 +
    8.47 +/*
    8.48 + * Processor
    8.49 + */
    8.50 +#define HVM_SAVE_TYPE_CPU  1
    8.51 +struct hvm_hw_cpu {
    8.52 +    uint64_t eip;
    8.53 +    uint64_t esp;
    8.54 +    uint64_t eflags;
    8.55 +    uint64_t cr0;
    8.56 +    uint64_t cr3;
    8.57 +    uint64_t cr4;
    8.58 +
    8.59 +    uint32_t cs_sel;
    8.60 +    uint32_t ds_sel;
    8.61 +    uint32_t es_sel;
    8.62 +    uint32_t fs_sel;
    8.63 +    uint32_t gs_sel;
    8.64 +    uint32_t ss_sel;
    8.65 +    uint32_t tr_sel;
    8.66 +    uint32_t ldtr_sel;
    8.67 +
    8.68 +    uint32_t cs_limit;
    8.69 +    uint32_t ds_limit;
    8.70 +    uint32_t es_limit;
    8.71 +    uint32_t fs_limit;
    8.72 +    uint32_t gs_limit;
    8.73 +    uint32_t ss_limit;
    8.74 +    uint32_t tr_limit;
    8.75 +    uint32_t ldtr_limit;
    8.76 +    uint32_t idtr_limit;
    8.77 +    uint32_t gdtr_limit;
    8.78 +
    8.79 +    uint64_t cs_base;
    8.80 +    uint64_t ds_base;
    8.81 +    uint64_t es_base;
    8.82 +    uint64_t fs_base;
    8.83 +    uint64_t gs_base;
    8.84 +    uint64_t ss_base;
    8.85 +    uint64_t tr_base;
    8.86 +    uint64_t ldtr_base;
    8.87 +    uint64_t idtr_base;
    8.88 +    uint64_t gdtr_base;
    8.89 +
    8.90 +
    8.91 +    uint32_t cs_arbytes;
    8.92 +    uint32_t ds_arbytes;
    8.93 +    uint32_t es_arbytes;
    8.94 +    uint32_t fs_arbytes;
    8.95 +    uint32_t gs_arbytes;
    8.96 +    uint32_t ss_arbytes;
    8.97 +    uint32_t tr_arbytes;
    8.98 +    uint32_t ldtr_arbytes;
    8.99 +
   8.100 +    uint32_t sysenter_cs;
   8.101 +    uint32_t padding0;
   8.102 +
   8.103 +    uint64_t sysenter_esp;
   8.104 +    uint64_t sysenter_eip;
   8.105 +
   8.106 +    /* msr for em64t */
   8.107 +    uint64_t shadow_gs;
   8.108 +    uint64_t flags;
   8.109 +
   8.110 +    /* same size as VMX_MSR_COUNT */
   8.111 +    uint64_t msr_items[6];
   8.112 +    uint64_t vmxassist_enabled;
   8.113 +};
   8.114 +
   8.115 +
   8.116 +/* 
   8.117 + *  PIT
   8.118 + */
   8.119 +#define HVM_SAVE_TYPE_PIT 2
   8.120 +struct hvm_hw_pit {
   8.121 +    struct hvm_hw_pit_channel {
   8.122 +        int64_t count_load_time;
   8.123 +        uint32_t count; /* can be 65536 */
   8.124 +        uint16_t latched_count;
   8.125 +        uint8_t count_latched;
   8.126 +        uint8_t status_latched;
   8.127 +        uint8_t status;
   8.128 +        uint8_t read_state;
   8.129 +        uint8_t write_state;
   8.130 +        uint8_t write_latch;
   8.131 +        uint8_t rw_mode;
   8.132 +        uint8_t mode;
   8.133 +        uint8_t bcd; /* not supported */
   8.134 +        uint8_t gate; /* timer start */
   8.135 +    } channels[3];  /* 3 x 24 bytes */
   8.136 +    uint32_t speaker_data_on;
   8.137 +};
   8.138 +
   8.139 +
   8.140 +
   8.141 +#endif /* __XEN_PUBLIC_HVM_SAVE_H__ */