direct-io.hg

changeset 15289:8ad38aaaeb89

hvm: Add locking to platform timers.
Handy for correctness.
Signed-off-by: Keir Fraser <keir@xensource.com>
author Keir Fraser <keir@xensource.com>
date Fri Jun 15 15:30:49 2007 +0100 (2007-06-15)
parents f1ba2e652724
children 56548d9a7ba7
files xen/arch/x86/hvm/hpet.c xen/arch/x86/hvm/hvm.c xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/pmtimer.c xen/arch/x86/hvm/rtc.c xen/arch/x86/hvm/vpt.c xen/common/timer.c xen/include/asm-x86/hvm/vcpu.h xen/include/asm-x86/hvm/vpt.h
line diff
     1.1 --- a/xen/arch/x86/hvm/hpet.c	Fri Jun 15 11:50:54 2007 +0100
     1.2 +++ b/xen/arch/x86/hvm/hpet.c	Fri Jun 15 15:30:49 2007 +0100
     1.3 @@ -113,6 +113,8 @@ static inline int hpet_check_access_leng
     1.4  
     1.5  static inline uint64_t hpet_read_maincounter(HPETState *h)
     1.6  {
     1.7 +    ASSERT(spin_is_locked(&h->lock));
     1.8 +
     1.9      if ( hpet_enabled(h) )
    1.10          return guest_time_hpet(h->vcpu) + h->mc_offset;
    1.11      else 
    1.12 @@ -131,6 +133,8 @@ static unsigned long hpet_read(
    1.13      if ( hpet_check_access_length(addr, length) != 0 )
    1.14          return ~0UL;
    1.15  
    1.16 +    spin_lock(&h->lock);
    1.17 +
    1.18      val = hpet_read64(h, addr & ~7);
    1.19      if ( (addr & ~7) == HPET_COUNTER )
    1.20          val = hpet_read_maincounter(h);
    1.21 @@ -139,12 +143,15 @@ static unsigned long hpet_read(
    1.22      if ( length != 8 )
    1.23          result = (val >> ((addr & 7) * 8)) & ((1UL << (length * 8)) - 1);
    1.24  
    1.25 +    spin_unlock(&h->lock);
    1.26 +
    1.27      return result;
    1.28  }
    1.29  
    1.30  static void hpet_stop_timer(HPETState *h, unsigned int tn)
    1.31  {
    1.32      ASSERT(tn < HPET_TIMER_NUM);
    1.33 +    ASSERT(spin_is_locked(&h->lock));
    1.34      stop_timer(&h->timers[tn]);
    1.35  }
    1.36  
    1.37 @@ -157,7 +164,8 @@ static void hpet_set_timer(HPETState *h,
    1.38      uint64_t tn_cmp, cur_tick, diff;
    1.39  
    1.40      ASSERT(tn < HPET_TIMER_NUM);
    1.41 -    
    1.42 +    ASSERT(spin_is_locked(&h->lock));
    1.43 +
    1.44      if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
    1.45          return;
    1.46  
    1.47 @@ -213,6 +221,8 @@ static void hpet_write(
    1.48      if ( hpet_check_access_length(addr, length) != 0 )
    1.49          return;
    1.50  
    1.51 +    spin_lock(&h->lock);
    1.52 +
    1.53      old_val = hpet_read64(h, addr & ~7);
    1.54      if ( (addr & ~7) == HPET_COUNTER )
    1.55          old_val = hpet_read_maincounter(h);
    1.56 @@ -302,6 +312,8 @@ static void hpet_write(
    1.57          /* Ignore writes to unsupported and reserved registers. */
    1.58          break;
    1.59      }
    1.60 +
    1.61 +    spin_unlock(&h->lock);
    1.62  }
    1.63  
    1.64  static int hpet_range(struct vcpu *v, unsigned long addr)
    1.65 @@ -321,6 +333,8 @@ static void hpet_route_interrupt(HPETSta
    1.66      unsigned int tn_int_route = timer_int_route(h, tn);
    1.67      struct domain *d = h->vcpu->domain;
    1.68  
    1.69 +    ASSERT(spin_is_locked(&h->lock));
    1.70 +
    1.71      if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) )
    1.72      {
    1.73          /* if LegacyReplacementRoute bit is set, HPET specification requires
    1.74 @@ -352,8 +366,13 @@ static void hpet_timer_fn(void *opaque)
    1.75      HPETState *h = htfi->hs;
    1.76      unsigned int tn = htfi->tn;
    1.77  
    1.78 +    spin_lock(&h->lock);
    1.79 +
    1.80      if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
    1.81 +    {
    1.82 +        spin_unlock(&h->lock);
    1.83          return;
    1.84 +    }
    1.85  
    1.86      hpet_route_interrupt(h, tn);
    1.87  
    1.88 @@ -374,6 +393,8 @@ static void hpet_timer_fn(void *opaque)
    1.89          set_timer(&h->timers[tn], 
    1.90                    NOW() + hpet_tick_to_ns(h, h->hpet.period[tn]));
    1.91      }
    1.92 +
    1.93 +    spin_unlock(&h->lock);
    1.94  }
    1.95  
    1.96  void hpet_migrate_timers(struct vcpu *v)
    1.97 @@ -391,12 +412,19 @@ void hpet_migrate_timers(struct vcpu *v)
    1.98  static int hpet_save(struct domain *d, hvm_domain_context_t *h)
    1.99  {
   1.100      HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
   1.101 +    int rc;
   1.102 +
   1.103 +    spin_lock(&hp->lock);
   1.104  
   1.105      /* Write the proper value into the main counter */
   1.106      hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu);
   1.107  
   1.108      /* Save the HPET registers */
   1.109 -    return hvm_save_entry(HPET, 0, h, &hp->hpet);
   1.110 +    rc = hvm_save_entry(HPET, 0, h, &hp->hpet);
   1.111 +
   1.112 +    spin_unlock(&hp->lock);
   1.113 +
   1.114 +    return rc;
   1.115  }
   1.116  
   1.117  static int hpet_load(struct domain *d, hvm_domain_context_t *h)
   1.118 @@ -404,9 +432,14 @@ static int hpet_load(struct domain *d, h
   1.119      HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
   1.120      int i;
   1.121  
   1.122 +    spin_lock(&hp->lock);
   1.123 +
   1.124      /* Reload the HPET registers */
   1.125      if ( hvm_load_entry(HPET, h, &hp->hpet) )
   1.126 +    {
   1.127 +        spin_unlock(&hp->lock);
   1.128          return -EINVAL;
   1.129 +    }
   1.130      
   1.131      /* Recalculate the offset between the main counter and guest time */
   1.132      hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu);
   1.133 @@ -415,6 +448,8 @@ static int hpet_load(struct domain *d, h
   1.134      for ( i = 0; i < HPET_TIMER_NUM; i++ )
   1.135          hpet_set_timer(hp, i);
   1.136  
   1.137 +    spin_unlock(&hp->lock);
   1.138 +
   1.139      return 0;
   1.140  }
   1.141  
   1.142 @@ -427,6 +462,8 @@ void hpet_init(struct vcpu *v)
   1.143  
   1.144      memset(h, 0, sizeof(HPETState));
   1.145  
   1.146 +    spin_lock_init(&h->lock);
   1.147 +
   1.148      h->vcpu = v;
   1.149      h->tsc_freq = ticks_per_sec(v);
   1.150  
     2.1 --- a/xen/arch/x86/hvm/hvm.c	Fri Jun 15 11:50:54 2007 +0100
     2.2 +++ b/xen/arch/x86/hvm/hvm.c	Fri Jun 15 15:30:49 2007 +0100
     2.3 @@ -401,6 +401,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
     2.4          get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
     2.5      spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock);
     2.6  
     2.7 +    spin_lock_init(&v->arch.hvm_vcpu.tm_lock);
     2.8      INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
     2.9  
    2.10      if ( v->vcpu_id == 0 )
     3.1 --- a/xen/arch/x86/hvm/i8254.c	Fri Jun 15 11:50:54 2007 +0100
     3.2 +++ b/xen/arch/x86/hvm/i8254.c	Fri Jun 15 15:30:49 2007 +0100
     3.3 @@ -82,6 +82,8 @@ static int pit_get_count(PITState *pit, 
     3.4      struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
     3.5      struct vcpu *v = vpit_vcpu(pit);
     3.6  
     3.7 +    ASSERT(spin_is_locked(&pit->lock));
     3.8 +
     3.9      d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
    3.10                   PIT_FREQ, ticks_per_sec(v));
    3.11  
    3.12 @@ -111,6 +113,8 @@ static int pit_get_out(PITState *pit, in
    3.13      int out;
    3.14      struct vcpu *v = vpit_vcpu(pit);
    3.15  
    3.16 +    ASSERT(spin_is_locked(&pit->lock));
    3.17 +
    3.18      d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], 
    3.19                   PIT_FREQ, ticks_per_sec(v));
    3.20  
    3.21 @@ -143,6 +147,8 @@ static void pit_set_gate(PITState *pit, 
    3.22      struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
    3.23      struct vcpu *v = vpit_vcpu(pit);
    3.24  
    3.25 +    ASSERT(spin_is_locked(&pit->lock));
    3.26 +
    3.27      switch ( s->mode )
    3.28      {
    3.29      default:
    3.30 @@ -165,6 +171,7 @@ static void pit_set_gate(PITState *pit, 
    3.31  
    3.32  int pit_get_gate(PITState *pit, int channel)
    3.33  {
    3.34 +    ASSERT(spin_is_locked(&pit->lock));
    3.35      return pit->hw.channels[channel].gate;
    3.36  }
    3.37  
    3.38 @@ -181,10 +188,15 @@ static void pit_load_count(PITState *pit
    3.39      struct periodic_time *pt = &pit->pt[channel];
    3.40      struct vcpu *v = vpit_vcpu(pit);
    3.41  
    3.42 +    ASSERT(spin_is_locked(&pit->lock));
    3.43 +
    3.44      if ( val == 0 )
    3.45          val = 0x10000;
    3.46  
    3.47 -    pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
    3.48 +    if ( v == NULL )
    3.49 +        rdtscll(pit->count_load_time[channel]);
    3.50 +    else
    3.51 +        pit->count_load_time[channel] = hvm_get_guest_time(v);
    3.52      s->count = val;
    3.53      period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
    3.54  
    3.55 @@ -209,23 +221,29 @@ static void pit_load_count(PITState *pit
    3.56      }
    3.57  }
    3.58  
    3.59 -static void pit_latch_count(PITState *s, int channel)
    3.60 +static void pit_latch_count(PITState *pit, int channel)
    3.61  {
    3.62 -    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
    3.63 +    struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
    3.64 +
    3.65 +    ASSERT(spin_is_locked(&pit->lock));
    3.66 +
    3.67      if ( !c->count_latched )
    3.68      {
    3.69 -        c->latched_count = pit_get_count(s, channel);
    3.70 +        c->latched_count = pit_get_count(pit, channel);
    3.71          c->count_latched = c->rw_mode;
    3.72      }
    3.73  }
    3.74  
    3.75 -static void pit_latch_status(PITState *s, int channel)
    3.76 +static void pit_latch_status(PITState *pit, int channel)
    3.77  {
    3.78 -    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
    3.79 +    struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
    3.80 +
    3.81 +    ASSERT(spin_is_locked(&pit->lock));
    3.82 +
    3.83      if ( !c->status_latched )
    3.84      {
    3.85          /* TODO: Return NULL COUNT (bit 6). */
    3.86 -        c->status = ((pit_get_out(s, channel) << 7) |
    3.87 +        c->status = ((pit_get_out(pit, channel) << 7) |
    3.88                       (c->rw_mode << 4) |
    3.89                       (c->mode << 1) |
    3.90                       c->bcd);
    3.91 @@ -241,6 +259,8 @@ static void pit_ioport_write(struct PITS
    3.92      val  &= 0xff;
    3.93      addr &= 3;
    3.94  
    3.95 +    spin_lock(&pit->lock);
    3.96 +
    3.97      if ( addr == 3 )
    3.98      {
    3.99          channel = val >> 6;
   3.100 @@ -304,6 +324,8 @@ static void pit_ioport_write(struct PITS
   3.101              break;
   3.102          }
   3.103      }
   3.104 +
   3.105 +    spin_unlock(&pit->lock);
   3.106  }
   3.107  
   3.108  static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
   3.109 @@ -314,6 +336,8 @@ static uint32_t pit_ioport_read(struct P
   3.110      addr &= 3;
   3.111      s = &pit->hw.channels[addr];
   3.112  
   3.113 +    spin_lock(&pit->lock);
   3.114 +
   3.115      if ( s->status_latched )
   3.116      {
   3.117          s->status_latched = 0;
   3.118 @@ -364,12 +388,16 @@ static uint32_t pit_ioport_read(struct P
   3.119          }
   3.120      }
   3.121  
   3.122 +    spin_unlock(&pit->lock);
   3.123 +
   3.124      return ret;
   3.125  }
   3.126  
   3.127  void pit_stop_channel0_irq(PITState *pit)
   3.128  {
   3.129 +    spin_lock(&pit->lock);
   3.130      destroy_periodic_time(&pit->pt[0]);
   3.131 +    spin_unlock(&pit->lock);
   3.132  }
   3.133  
   3.134  #ifdef HVM_DEBUG_SUSPEND
   3.135 @@ -422,11 +450,18 @@ static void pit_info(PITState *pit)
   3.136  static int pit_save(struct domain *d, hvm_domain_context_t *h)
   3.137  {
   3.138      PITState *pit = domain_vpit(d);
   3.139 +    int rc;
   3.140 +
   3.141 +    spin_lock(&pit->lock);
   3.142      
   3.143      pit_info(pit);
   3.144  
   3.145      /* Save the PIT hardware state */
   3.146 -    return hvm_save_entry(PIT, 0, h, &pit->hw);
   3.147 +    rc = hvm_save_entry(PIT, 0, h, &pit->hw);
   3.148 +
   3.149 +    spin_unlock(&pit->lock);
   3.150 +
   3.151 +    return rc;
   3.152  }
   3.153  
   3.154  static int pit_load(struct domain *d, hvm_domain_context_t *h)
   3.155 @@ -434,9 +469,14 @@ static int pit_load(struct domain *d, hv
   3.156      PITState *pit = domain_vpit(d);
   3.157      int i;
   3.158  
   3.159 +    spin_lock(&pit->lock);
   3.160 +
   3.161      /* Restore the PIT hardware state */
   3.162      if ( hvm_load_entry(PIT, h, &pit->hw) )
   3.163 +    {
   3.164 +        spin_unlock(&pit->lock);
   3.165          return 1;
   3.166 +    }
   3.167      
   3.168      /* Recreate platform timers from hardware state.  There will be some 
   3.169       * time jitter here, but the wall-clock will have jumped massively, so 
   3.170 @@ -448,6 +488,9 @@ static int pit_load(struct domain *d, hv
   3.171      }
   3.172  
   3.173      pit_info(pit);
   3.174 +
   3.175 +    spin_unlock(&pit->lock);
   3.176 +
   3.177      return 0;
   3.178  }
   3.179  
   3.180 @@ -456,17 +499,15 @@ HVM_REGISTER_SAVE_RESTORE(PIT, pit_save,
   3.181  void pit_init(struct vcpu *v, unsigned long cpu_khz)
   3.182  {
   3.183      PITState *pit = vcpu_vpit(v);
   3.184 -    struct periodic_time *pt;
   3.185      struct hvm_hw_pit_channel *s;
   3.186      int i;
   3.187  
   3.188 -    pt = &pit->pt[0];  
   3.189 -    pt[0].vcpu = v;
   3.190 -    pt[1].vcpu = v;
   3.191 -    pt[2].vcpu = v;
   3.192 +    spin_lock_init(&pit->lock);
   3.193 +
   3.194 +    /* Some sub-functions assert that they are called with the lock held. */
   3.195 +    spin_lock(&pit->lock);
   3.196  
   3.197      register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
   3.198 -    /* register the speaker port */
   3.199      register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
   3.200      ticks_per_sec(v) = cpu_khz * (int64_t)1000;
   3.201  
   3.202 @@ -477,6 +518,8 @@ void pit_init(struct vcpu *v, unsigned l
   3.203          s->gate = (i != 2);
   3.204          pit_load_count(pit, i, 0);
   3.205      }
   3.206 +
   3.207 +    spin_unlock(&pit->lock);
   3.208  }
   3.209  
   3.210  void pit_deinit(struct domain *d)
   3.211 @@ -492,10 +535,10 @@ static int handle_pit_io(ioreq_t *p)
   3.212  
   3.213      if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
   3.214      {
   3.215 -        gdprintk(XENLOG_WARNING, "HVM_PIT bad access\n");
   3.216 +        gdprintk(XENLOG_WARNING, "PIT bad access\n");
   3.217          return 1;
   3.218      }
   3.219 -    
   3.220 +
   3.221      if ( p->dir == IOREQ_WRITE )
   3.222      {
   3.223          pit_ioport_write(vpit, p->addr, p->data);
   3.224 @@ -505,7 +548,7 @@ static int handle_pit_io(ioreq_t *p)
   3.225          if ( (p->addr & 3) != 3 )
   3.226              p->data = pit_ioport_read(vpit, p->addr);
   3.227          else
   3.228 -            gdprintk(XENLOG_WARNING, "HVM_PIT: read A1:A0=3!\n");
   3.229 +            gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n");
   3.230      }
   3.231  
   3.232      return 1;
   3.233 @@ -533,15 +576,19 @@ static int handle_speaker_io(ioreq_t *p)
   3.234  
   3.235      if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
   3.236      {
   3.237 -        gdprintk(XENLOG_WARNING, "HVM_SPEAKER bad access\n");
   3.238 +        gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n");
   3.239          return 1;
   3.240      }
   3.241  
   3.242 +    spin_lock(&vpit->lock);
   3.243 +
   3.244      if ( p->dir == IOREQ_WRITE )
   3.245          speaker_ioport_write(vpit, p->addr, p->data);
   3.246      else
   3.247          p->data = speaker_ioport_read(vpit, p->addr);
   3.248  
   3.249 +    spin_unlock(&vpit->lock);
   3.250 +
   3.251      return 1;
   3.252  }
   3.253  
     4.1 --- a/xen/arch/x86/hvm/pmtimer.c	Fri Jun 15 11:50:54 2007 +0100
     4.2 +++ b/xen/arch/x86/hvm/pmtimer.c	Fri Jun 15 15:30:49 2007 +0100
     4.3 @@ -53,6 +53,8 @@
     4.4  /* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */
     4.5  static void pmt_update_sci(PMTState *s)
     4.6  {
     4.7 +    ASSERT(spin_is_locked(&s->lock));
     4.8 +
     4.9      if ( s->pm.pm1a_en & s->pm.pm1a_sts & SCI_MASK )
    4.10          hvm_isa_irq_assert(s->vcpu->domain, SCI_IRQ);
    4.11      else
    4.12 @@ -66,6 +68,8 @@ static void pmt_update_time(PMTState *s)
    4.13      uint64_t curr_gtime;
    4.14      uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB;
    4.15      
    4.16 +    ASSERT(spin_is_locked(&s->lock));
    4.17 +
    4.18      /* Update the timer */
    4.19      curr_gtime = hvm_get_guest_time(s->vcpu);
    4.20      s->pm.tmr_val += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
    4.21 @@ -89,6 +93,8 @@ static void pmt_timer_callback(void *opa
    4.22      uint32_t pmt_cycles_until_flip;
    4.23      uint64_t time_until_flip;
    4.24  
    4.25 +    spin_lock(&s->lock);
    4.26 +
    4.27      /* Recalculate the timer and make sure we get an SCI if we need one */
    4.28      pmt_update_time(s);
    4.29  
    4.30 @@ -103,9 +109,10 @@ static void pmt_timer_callback(void *opa
    4.31  
    4.32      /* Wake up again near the next bit-flip */
    4.33      set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1));
    4.34 +
    4.35 +    spin_unlock(&s->lock);
    4.36  }
    4.37  
    4.38 -
    4.39  /* Handle port I/O to the PM1a_STS and PM1a_EN registers */
    4.40  static int handle_evt_io(ioreq_t *p)
    4.41  {
    4.42 @@ -114,7 +121,9 @@ static int handle_evt_io(ioreq_t *p)
    4.43      uint32_t addr, data, byte;
    4.44      int i;
    4.45  
    4.46 -    if ( p->dir == 0 ) /* Write */
    4.47 +    spin_lock(&s->lock);
    4.48 +
    4.49 +    if ( p->dir == IOREQ_WRITE )
    4.50      {
    4.51          /* Handle this I/O one byte at a time */
    4.52          for ( i = p->size, addr = p->addr, data = p->data;
    4.53 @@ -122,7 +131,7 @@ static int handle_evt_io(ioreq_t *p)
    4.54                i--, addr++, data >>= 8 )
    4.55          {
    4.56              byte = data & 0xff;
    4.57 -            switch(addr) 
    4.58 +            switch ( addr )
    4.59              {
    4.60                  /* PM1a_STS register bits are write-to-clear */
    4.61              case PM1a_STS_ADDR:
    4.62 @@ -149,7 +158,7 @@ static int handle_evt_io(ioreq_t *p)
    4.63          /* Fix up the SCI state to match the new register state */
    4.64          pmt_update_sci(s);
    4.65      }
    4.66 -    else /* Read */
    4.67 +    else /* p->dir == IOREQ_READ */
    4.68      {
    4.69          data = s->pm.pm1a_sts | (((uint32_t) s->pm.pm1a_en) << 16);
    4.70          data >>= 8 * (p->addr - PM1a_STS_ADDR);
    4.71 @@ -157,6 +166,9 @@ static int handle_evt_io(ioreq_t *p)
    4.72          else if ( p->size == 2 ) data &= 0xffff;
    4.73          p->data = data;
    4.74      }
    4.75 +
    4.76 +    spin_unlock(&s->lock);
    4.77 +
    4.78      return 1;
    4.79  }
    4.80  
    4.81 @@ -167,29 +179,31 @@ static int handle_pmt_io(ioreq_t *p)
    4.82      struct vcpu *v = current;
    4.83      PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
    4.84  
    4.85 -    if (p->size != 4 ||
    4.86 -        p->data_is_ptr ||
    4.87 -        p->type != IOREQ_TYPE_PIO){
    4.88 -        printk("HVM_PMT: wrong PM timer IO\n");
    4.89 +    if ( (p->size != 4) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
    4.90 +    {
    4.91 +        gdprintk(XENLOG_WARNING, "HVM_PMT bad access\n");
    4.92          return 1;
    4.93      }
    4.94      
    4.95 -    if (p->dir == 0) { /* write */
    4.96 -        /* PM_TMR_BLK is read-only */
    4.97 -        return 1;
    4.98 -    } else if (p->dir == 1) { /* read */
    4.99 +    if ( p->dir == IOREQ_READ )
   4.100 +    {
   4.101 +        spin_lock(&s->lock);
   4.102          pmt_update_time(s);
   4.103          p->data = s->pm.tmr_val;
   4.104 +        spin_unlock(&s->lock);
   4.105          return 1;
   4.106      }
   4.107 +
   4.108      return 0;
   4.109  }
   4.110  
   4.111  static int pmtimer_save(struct domain *d, hvm_domain_context_t *h)
   4.112  {
   4.113      PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
   4.114 -    uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB;
   4.115 -    uint32_t x;
   4.116 +    uint32_t x, msb = s->pm.tmr_val & TMR_VAL_MSB;
   4.117 +    int rc;
   4.118 +
   4.119 +    spin_lock(&s->lock);
   4.120  
   4.121      /* Update the counter to the guest's current time.  We always save
   4.122       * with the domain paused, so the saved time should be after the
   4.123 @@ -202,22 +216,33 @@ static int pmtimer_save(struct domain *d
   4.124      /* No point in setting the SCI here because we'll already have saved the 
   4.125       * IRQ and *PIC state; we'll fix it up when we restore the domain */
   4.126  
   4.127 -    return hvm_save_entry(PMTIMER, 0, h, &s->pm);
   4.128 +    rc = hvm_save_entry(PMTIMER, 0, h, &s->pm);
   4.129 +
   4.130 +    spin_unlock(&s->lock);
   4.131 +
   4.132 +    return rc;
   4.133  }
   4.134  
   4.135  static int pmtimer_load(struct domain *d, hvm_domain_context_t *h)
   4.136  {
   4.137      PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
   4.138  
   4.139 +    spin_lock(&s->lock);
   4.140 +
   4.141      /* Reload the registers */
   4.142      if ( hvm_load_entry(PMTIMER, h, &s->pm) )
   4.143 +    {
   4.144 +        spin_unlock(&s->lock);
   4.145          return -EINVAL;
   4.146 +    }
   4.147  
   4.148      /* Calculate future counter values from now. */
   4.149      s->last_gtime = hvm_get_guest_time(s->vcpu);
   4.150  
   4.151      /* Set the SCI state from the registers */ 
   4.152      pmt_update_sci(s);
   4.153 +
   4.154 +    spin_unlock(&s->lock);
   4.155      
   4.156      return 0;
   4.157  }
   4.158 @@ -225,14 +250,11 @@ static int pmtimer_load(struct domain *d
   4.159  HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, 
   4.160                            1, HVMSR_PER_DOM);
   4.161  
   4.162 -
   4.163  void pmtimer_init(struct vcpu *v)
   4.164  {
   4.165      PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
   4.166  
   4.167 -    s->pm.tmr_val = 0;
   4.168 -    s->pm.pm1a_sts = 0;
   4.169 -    s->pm.pm1a_en = 0;
   4.170 +    spin_lock_init(&s->lock);
   4.171  
   4.172      s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v);
   4.173      s->vcpu = v;
     5.1 --- a/xen/arch/x86/hvm/rtc.c	Fri Jun 15 11:50:54 2007 +0100
     5.2 +++ b/xen/arch/x86/hvm/rtc.c	Fri Jun 15 15:30:49 2007 +0100
     5.3 @@ -34,10 +34,12 @@
     5.4                                         arch.hvm_domain.pl_time.vrtc))
     5.5  #define vrtc_vcpu(rtc)   (vrtc_domain(rtc)->vcpu[0])
     5.6  
     5.7 -void rtc_periodic_cb(struct vcpu *v, void *opaque)
     5.8 +static void rtc_periodic_cb(struct vcpu *v, void *opaque)
     5.9  {
    5.10      RTCState *s = opaque;
    5.11 +    spin_lock(&s->lock);
    5.12      s->hw.cmos_data[RTC_REG_C] |= 0xc0;
    5.13 +    spin_unlock(&s->lock);
    5.14  }
    5.15  
    5.16  int is_rtc_periodic_irq(void *opaque)
    5.17 @@ -55,6 +57,8 @@ static void rtc_timer_update(RTCState *s
    5.18      int period_code, period;
    5.19      struct vcpu *v = vrtc_vcpu(s);
    5.20  
    5.21 +    ASSERT(spin_is_locked(&s->lock));
    5.22 +
    5.23      period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
    5.24      if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) )
    5.25      {
    5.26 @@ -78,14 +82,21 @@ static int rtc_ioport_write(void *opaque
    5.27  {
    5.28      RTCState *s = opaque;
    5.29  
    5.30 +    spin_lock(&s->lock);
    5.31 +
    5.32      if ( (addr & 1) == 0 )
    5.33      {
    5.34 -        s->hw.cmos_index = data & 0x7f;
    5.35 -        return (s->hw.cmos_index < RTC_CMOS_SIZE);
    5.36 +        data &= 0x7f;
    5.37 +        s->hw.cmos_index = data;
    5.38 +        spin_unlock(&s->lock);
    5.39 +        return (data < RTC_CMOS_SIZE);
    5.40      }
    5.41  
    5.42      if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
    5.43 +    {
    5.44 +        spin_unlock(&s->lock);
    5.45          return 0;
    5.46 +    }
    5.47  
    5.48      switch ( s->hw.cmos_index )
    5.49      {
    5.50 @@ -134,6 +145,8 @@ static int rtc_ioport_write(void *opaque
    5.51          break;
    5.52      }
    5.53  
    5.54 +    spin_unlock(&s->lock);
    5.55 +
    5.56      return 1;
    5.57  }
    5.58  
    5.59 @@ -158,6 +171,8 @@ static void rtc_set_time(RTCState *s)
    5.60      struct tm *tm = &s->current_tm;
    5.61      unsigned long before, after; /* XXX s_time_t */
    5.62        
    5.63 +    ASSERT(spin_is_locked(&s->lock));
    5.64 +
    5.65      before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
    5.66  		    tm->tm_hour, tm->tm_min, tm->tm_sec);
    5.67      
    5.68 @@ -182,6 +197,8 @@ static void rtc_copy_date(RTCState *s)
    5.69      const struct tm *tm = &s->current_tm;
    5.70      struct domain *d = vrtc_domain(s);
    5.71  
    5.72 +    ASSERT(spin_is_locked(&s->lock));
    5.73 +
    5.74      if ( s->time_offset_seconds != d->time_offset_seconds )
    5.75      {
    5.76          s->current_tm = gmtime(get_localtime(d));
    5.77 @@ -231,6 +248,8 @@ static void rtc_next_second(RTCState *s)
    5.78      int days_in_month;
    5.79      struct domain *d = vrtc_domain(s);
    5.80  
    5.81 +    ASSERT(spin_is_locked(&s->lock));
    5.82 +
    5.83      if ( s->time_offset_seconds != d->time_offset_seconds )
    5.84      {
    5.85          s->current_tm = gmtime(get_localtime(d));
    5.86 @@ -279,6 +298,8 @@ static void rtc_update_second(void *opaq
    5.87  {
    5.88      RTCState *s = opaque;
    5.89  
    5.90 +    spin_lock(&s->lock);
    5.91 +
    5.92      /* if the oscillator is not in normal operation, we do not update */
    5.93      if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
    5.94      {
    5.95 @@ -295,6 +316,8 @@ static void rtc_update_second(void *opaq
    5.96          /* Delay time before update cycle */
    5.97          set_timer(&s->second_timer2, s->next_second_time + 244000);
    5.98      }
    5.99 +
   5.100 +    spin_unlock(&s->lock);
   5.101  }
   5.102  
   5.103  static void rtc_update_second2(void *opaque)
   5.104 @@ -302,6 +325,8 @@ static void rtc_update_second2(void *opa
   5.105      RTCState *s = opaque;
   5.106      struct domain *d = vrtc_domain(s);
   5.107  
   5.108 +    spin_lock(&s->lock);
   5.109 +
   5.110      if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
   5.111          rtc_copy_date(s);
   5.112  
   5.113 @@ -337,16 +362,19 @@ static void rtc_update_second2(void *opa
   5.114  
   5.115      s->next_second_time += 1000000000ULL;
   5.116      set_timer(&s->second_timer, s->next_second_time);
   5.117 +
   5.118 +    spin_unlock(&s->lock);
   5.119  }
   5.120  
   5.121 -static uint32_t rtc_ioport_read(void *opaque, uint32_t addr)
   5.122 +static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
   5.123  {
   5.124 -    RTCState *s = opaque;
   5.125      int ret;
   5.126  
   5.127      if ( (addr & 1) == 0 )
   5.128          return 0xff;
   5.129  
   5.130 +    spin_lock(&s->lock);
   5.131 +
   5.132      switch ( s->hw.cmos_index )
   5.133      {
   5.134      case RTC_SECONDS:
   5.135 @@ -371,6 +399,8 @@ static uint32_t rtc_ioport_read(void *op
   5.136          break;
   5.137      }
   5.138  
   5.139 +    spin_unlock(&s->lock);
   5.140 +
   5.141      return ret;
   5.142  }
   5.143  
   5.144 @@ -413,7 +443,11 @@ void rtc_migrate_timers(struct vcpu *v)
   5.145  static int rtc_save(struct domain *d, hvm_domain_context_t *h)
   5.146  {
   5.147      RTCState *s = domain_vrtc(d);
   5.148 -    return hvm_save_entry(RTC, 0, h, &s->hw);
   5.149 +    int rc;
   5.150 +    spin_lock(&s->lock);
   5.151 +    rc = hvm_save_entry(RTC, 0, h, &s->hw);
   5.152 +    spin_unlock(&s->lock);
   5.153 +    return rc;
   5.154  }
   5.155  
   5.156  /* Reload the hardware state from a saved domain */
   5.157 @@ -421,9 +455,14 @@ static int rtc_load(struct domain *d, hv
   5.158  {
   5.159      RTCState *s = domain_vrtc(d);
   5.160  
   5.161 +    spin_lock(&s->lock);
   5.162 +
   5.163      /* Restore the registers */
   5.164      if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
   5.165 +    {
   5.166 +        spin_unlock(&s->lock);
   5.167          return -EINVAL;
   5.168 +    }
   5.169  
   5.170      /* Reset the wall-clock time.  In normal running, this runs with host 
   5.171       * time, so let's keep doing that. */
   5.172 @@ -436,6 +475,8 @@ static int rtc_load(struct domain *d, hv
   5.173      /* Reset the periodic interrupt timer based on the registers */
   5.174      rtc_timer_update(s);
   5.175  
   5.176 +    spin_unlock(&s->lock);
   5.177 +
   5.178      return 0;
   5.179  }
   5.180  
   5.181 @@ -446,13 +487,18 @@ void rtc_init(struct vcpu *v, int base)
   5.182  {
   5.183      RTCState *s = vcpu_vrtc(v);
   5.184  
   5.185 +    spin_lock_init(&s->lock);
   5.186 +
   5.187      s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
   5.188      s->hw.cmos_data[RTC_REG_B] = RTC_24H;
   5.189      s->hw.cmos_data[RTC_REG_C] = 0;
   5.190      s->hw.cmos_data[RTC_REG_D] = RTC_VRT;
   5.191  
   5.192      s->current_tm = gmtime(get_localtime(v->domain));
   5.193 +
   5.194 +    spin_lock(&s->lock);
   5.195      rtc_copy_date(s);
   5.196 +    spin_unlock(&s->lock);
   5.197  
   5.198      init_timer(&s->second_timer, rtc_update_second, s, v->processor);
   5.199      init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
     6.1 --- a/xen/arch/x86/hvm/vpt.c	Fri Jun 15 11:50:54 2007 +0100
     6.2 +++ b/xen/arch/x86/hvm/vpt.c	Fri Jun 15 15:30:49 2007 +0100
     6.3 @@ -17,11 +17,31 @@
     6.4   * Place - Suite 330, Boston, MA 02111-1307 USA.
     6.5   *
     6.6   */
     6.7 +
     6.8  #include <xen/time.h>
     6.9  #include <asm/hvm/support.h>
    6.10  #include <asm/hvm/vpt.h>
    6.11  #include <asm/event.h>
    6.12  
    6.13 +static void pt_lock(struct periodic_time *pt)
    6.14 +{
    6.15 +    struct vcpu *v;
    6.16 +
    6.17 +    for ( ; ; )
    6.18 +    {
    6.19 +        v = pt->vcpu;
    6.20 +        spin_lock(&v->arch.hvm_vcpu.tm_lock);
    6.21 +        if ( likely(pt->vcpu == v) )
    6.22 +            break;
    6.23 +        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    6.24 +    }
    6.25 +}
    6.26 +
    6.27 +static void pt_unlock(struct periodic_time *pt)
    6.28 +{
    6.29 +    spin_unlock(&pt->vcpu->arch.hvm_vcpu.tm_lock);
    6.30 +}
    6.31 +
    6.32  static void missed_ticks(struct periodic_time *pt)
    6.33  {
    6.34      s_time_t missed_ticks;
    6.35 @@ -52,10 +72,14 @@ void pt_freeze_time(struct vcpu *v)
    6.36      if ( test_bit(_VPF_blocked, &v->pause_flags) )
    6.37          return;
    6.38  
    6.39 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
    6.40 +
    6.41      v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
    6.42  
    6.43      list_for_each_entry ( pt, head, list )
    6.44          stop_timer(&pt->timer);
    6.45 +
    6.46 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    6.47  }
    6.48  
    6.49  void pt_thaw_time(struct vcpu *v)
    6.50 @@ -63,6 +87,8 @@ void pt_thaw_time(struct vcpu *v)
    6.51      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
    6.52      struct periodic_time *pt;
    6.53  
    6.54 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
    6.55 +
    6.56      if ( v->arch.hvm_vcpu.guest_time )
    6.57      {
    6.58          hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
    6.59 @@ -74,12 +100,16 @@ void pt_thaw_time(struct vcpu *v)
    6.60              set_timer(&pt->timer, pt->scheduled);
    6.61          }
    6.62      }
    6.63 +
    6.64 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    6.65  }
    6.66  
    6.67  static void pt_timer_fn(void *data)
    6.68  {
    6.69      struct periodic_time *pt = data;
    6.70  
    6.71 +    pt_lock(pt);
    6.72 +
    6.73      pt->pending_intr_nr++;
    6.74      pt->scheduled += pt->period;
    6.75  
    6.76 @@ -89,6 +119,8 @@ static void pt_timer_fn(void *data)
    6.77          set_timer(&pt->timer, pt->scheduled);
    6.78  
    6.79      vcpu_kick(pt->vcpu);
    6.80 +
    6.81 +    pt_unlock(pt);
    6.82  }
    6.83  
    6.84  void pt_update_irq(struct vcpu *v)
    6.85 @@ -98,6 +130,8 @@ void pt_update_irq(struct vcpu *v)
    6.86      uint64_t max_lag = -1ULL;
    6.87      int irq = -1;
    6.88  
    6.89 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
    6.90 +
    6.91      list_for_each_entry ( pt, head, list )
    6.92      {
    6.93          if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
    6.94 @@ -108,6 +142,8 @@ void pt_update_irq(struct vcpu *v)
    6.95          }
    6.96      }
    6.97  
    6.98 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
    6.99 +
   6.100      if ( is_lvtt(v, irq) )
   6.101      {
   6.102          vlapic_set_irq(vcpu_vlapic(v), irq, 0);
   6.103 @@ -119,7 +155,7 @@ void pt_update_irq(struct vcpu *v)
   6.104      }
   6.105  }
   6.106  
   6.107 -struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
   6.108 +static struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
   6.109  {
   6.110      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
   6.111      struct periodic_time *pt;
   6.112 @@ -152,19 +188,34 @@ struct periodic_time *is_pt_irq(struct v
   6.113  
   6.114  void pt_intr_post(struct vcpu *v, int vector, int type)
   6.115  {
   6.116 -    struct periodic_time *pt = is_pt_irq(v, vector, type);
   6.117 +    struct periodic_time *pt;
   6.118 +    time_cb *cb;
   6.119 +    void *cb_priv;
   6.120 +
   6.121 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
   6.122  
   6.123 +    pt = is_pt_irq(v, vector, type);
   6.124      if ( pt == NULL )
   6.125 +    {
   6.126 +        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
   6.127          return;
   6.128 +    }
   6.129 +
   6.130 +    ASSERT(pt->vcpu == v);
   6.131  
   6.132      pt->pending_intr_nr--;
   6.133      pt->last_plt_gtime += pt->period_cycles;
   6.134  
   6.135 -    if ( hvm_get_guest_time(pt->vcpu) < pt->last_plt_gtime )
   6.136 -        hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
   6.137 +    if ( hvm_get_guest_time(v) < pt->last_plt_gtime )
   6.138 +        hvm_set_guest_time(v, pt->last_plt_gtime);
   6.139  
   6.140 -    if ( pt->cb != NULL )
   6.141 -        pt->cb(pt->vcpu, pt->priv);
   6.142 +    cb = pt->cb;
   6.143 +    cb_priv = pt->priv;
   6.144 +
   6.145 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
   6.146 +
   6.147 +    if ( cb != NULL )
   6.148 +        cb(v, cb_priv);
   6.149  }
   6.150  
   6.151  void pt_reset(struct vcpu *v)
   6.152 @@ -172,6 +223,8 @@ void pt_reset(struct vcpu *v)
   6.153      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
   6.154      struct periodic_time *pt;
   6.155  
   6.156 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
   6.157 +
   6.158      list_for_each_entry ( pt, head, list )
   6.159      {
   6.160          if ( pt->enabled )
   6.161 @@ -182,6 +235,8 @@ void pt_reset(struct vcpu *v)
   6.162              set_timer(&pt->timer, pt->scheduled);
   6.163          }
   6.164      }
   6.165 +
   6.166 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
   6.167  }
   6.168  
   6.169  void pt_migrate(struct vcpu *v)
   6.170 @@ -189,11 +244,15 @@ void pt_migrate(struct vcpu *v)
   6.171      struct list_head *head = &v->arch.hvm_vcpu.tm_list;
   6.172      struct periodic_time *pt;
   6.173  
   6.174 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
   6.175 +
   6.176      list_for_each_entry ( pt, head, list )
   6.177      {
   6.178          if ( pt->enabled )
   6.179              migrate_timer(&pt->timer, v->processor);
   6.180      }
   6.181 +
   6.182 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
   6.183  }
   6.184  
   6.185  void create_periodic_time(
   6.186 @@ -202,6 +261,8 @@ void create_periodic_time(
   6.187  {
   6.188      destroy_periodic_time(pt);
   6.189  
   6.190 +    spin_lock(&v->arch.hvm_vcpu.tm_lock);
   6.191 +
   6.192      init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
   6.193      pt->enabled = 1;
   6.194      if ( period < 900000 ) /* < 0.9 ms */
   6.195 @@ -223,6 +284,8 @@ void create_periodic_time(
   6.196  
   6.197      list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
   6.198      set_timer(&pt->timer, pt->scheduled);
   6.199 +
   6.200 +    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
   6.201  }
   6.202  
   6.203  void destroy_periodic_time(struct periodic_time *pt)
   6.204 @@ -230,8 +293,10 @@ void destroy_periodic_time(struct period
   6.205      if ( !pt->enabled )
   6.206          return;
   6.207  
   6.208 +    pt_lock(pt);
   6.209      pt->enabled = 0;
   6.210      pt->pending_intr_nr = 0;
   6.211      list_del(&pt->list);
   6.212      kill_timer(&pt->timer);
   6.213 +    pt_unlock(pt);
   6.214  }
     7.1 --- a/xen/common/timer.c	Fri Jun 15 11:50:54 2007 +0100
     7.2 +++ b/xen/common/timer.c	Fri Jun 15 15:30:49 2007 +0100
     7.3 @@ -183,7 +183,7 @@ static inline void timer_lock(struct tim
     7.4  
     7.5  static inline void timer_unlock(struct timer *timer)
     7.6  {
     7.7 -        spin_unlock(&per_cpu(timers, timer->cpu).lock);
     7.8 +    spin_unlock(&per_cpu(timers, timer->cpu).lock);
     7.9  }
    7.10  
    7.11  #define timer_unlock_irq(t) \
     8.1 --- a/xen/include/asm-x86/hvm/vcpu.h	Fri Jun 15 11:50:54 2007 +0100
     8.2 +++ b/xen/include/asm-x86/hvm/vcpu.h	Fri Jun 15 15:30:49 2007 +0100
     8.3 @@ -35,6 +35,9 @@ struct hvm_vcpu {
     8.4      struct vlapic       vlapic;
     8.5      s64                 cache_tsc_offset;
     8.6      u64                 guest_time;
     8.7 +
     8.8 +    /* Lock and list for virtual platform timers. */
     8.9 +    spinlock_t          tm_lock;
    8.10      struct list_head    tm_list;
    8.11  
    8.12      /* For AP startup */
     9.1 --- a/xen/include/asm-x86/hvm/vpt.h	Fri Jun 15 11:50:54 2007 +0100
     9.2 +++ b/xen/include/asm-x86/hvm/vpt.h	Fri Jun 15 15:30:49 2007 +0100
     9.3 @@ -31,7 +31,6 @@
     9.4  #include <asm/hvm/vpic.h>
     9.5  #include <public/hvm/save.h>
     9.6  
     9.7 -
     9.8  struct HPETState;
     9.9  struct HPET_timer_fn_info {
    9.10      struct HPETState       *hs;
    9.11 @@ -45,6 +44,7 @@ typedef struct HPETState {
    9.12      uint64_t mc_offset;
    9.13      struct timer timers[HPET_TIMER_NUM];
    9.14      struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM]; 
    9.15 +    spinlock_t lock;
    9.16  } HPETState;
    9.17  
    9.18  
    9.19 @@ -80,6 +80,7 @@ typedef struct PITState {
    9.20      int64_t count_load_time[3];
    9.21      /* irq handling */
    9.22      struct periodic_time pt[3];
    9.23 +    spinlock_t lock;
    9.24  } PITState;
    9.25  
    9.26  typedef struct RTCState {
    9.27 @@ -93,6 +94,7 @@ typedef struct RTCState {
    9.28      struct timer second_timer2;
    9.29      struct periodic_time pt;
    9.30      int32_t time_offset_seconds;
    9.31 +    spinlock_t lock;
    9.32  } RTCState;
    9.33  
    9.34  #define FREQUENCE_PMTIMER  3579545  /* Timer should run at 3.579545 MHz */
    9.35 @@ -102,6 +104,7 @@ typedef struct PMTState {
    9.36      uint64_t last_gtime;        /* Last (guest) time we updated the timer */
    9.37      uint64_t scale;             /* Multiplier to get from tsc to timer ticks */
    9.38      struct timer timer;         /* To make sure we send SCIs */
    9.39 +    spinlock_t lock;
    9.40  } PMTState;
    9.41  
    9.42  struct pl_time {    /* platform time */
    9.43 @@ -116,7 +119,6 @@ struct pl_time {    /* platform time */
    9.44  void pt_freeze_time(struct vcpu *v);
    9.45  void pt_thaw_time(struct vcpu *v);
    9.46  void pt_update_irq(struct vcpu *v);
    9.47 -struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
    9.48  void pt_intr_post(struct vcpu *v, int vector, int type);
    9.49  void pt_reset(struct vcpu *v);
    9.50  void pt_migrate(struct vcpu *v);