WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm: Add locking to platform timers.

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm: Add locking to platform timers.
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Fri, 15 Jun 2007 16:20:09 -0700
Delivery-date: Fri, 15 Jun 2007 16:18:40 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxxxxxxxx>
# Date 1181917849 -3600
# Node ID 8ad38aaaeb89bfa67fc30ca5c4b2d3a78af219ce
# Parent  f1ba2e652724cb505a85eef64eaafe9774421011
hvm: Add locking to platform timers.
Handy for correctness.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
 xen/arch/x86/hvm/hpet.c        |   43 ++++++++++++++++++--
 xen/arch/x86/hvm/hvm.c         |    1 
 xen/arch/x86/hvm/i8254.c       |   87 +++++++++++++++++++++++++++++++----------
 xen/arch/x86/hvm/pmtimer.c     |   62 +++++++++++++++++++----------
 xen/arch/x86/hvm/rtc.c         |   64 +++++++++++++++++++++++++-----
 xen/arch/x86/hvm/vpt.c         |   85 +++++++++++++++++++++++++++++++++++-----
 xen/common/timer.c             |    2 
 xen/include/asm-x86/hvm/vcpu.h |    3 +
 xen/include/asm-x86/hvm/vpt.h  |    6 +-
 9 files changed, 288 insertions(+), 65 deletions(-)

diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/hpet.c
--- a/xen/arch/x86/hvm/hpet.c   Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/hpet.c   Fri Jun 15 15:30:49 2007 +0100
@@ -113,6 +113,8 @@ static inline int hpet_check_access_leng
 
 static inline uint64_t hpet_read_maincounter(HPETState *h)
 {
+    ASSERT(spin_is_locked(&h->lock));
+
     if ( hpet_enabled(h) )
         return guest_time_hpet(h->vcpu) + h->mc_offset;
     else 
@@ -131,6 +133,8 @@ static unsigned long hpet_read(
     if ( hpet_check_access_length(addr, length) != 0 )
         return ~0UL;
 
+    spin_lock(&h->lock);
+
     val = hpet_read64(h, addr & ~7);
     if ( (addr & ~7) == HPET_COUNTER )
         val = hpet_read_maincounter(h);
@@ -139,12 +143,15 @@ static unsigned long hpet_read(
     if ( length != 8 )
         result = (val >> ((addr & 7) * 8)) & ((1UL << (length * 8)) - 1);
 
+    spin_unlock(&h->lock);
+
     return result;
 }
 
 static void hpet_stop_timer(HPETState *h, unsigned int tn)
 {
     ASSERT(tn < HPET_TIMER_NUM);
+    ASSERT(spin_is_locked(&h->lock));
     stop_timer(&h->timers[tn]);
 }
 
@@ -157,7 +164,8 @@ static void hpet_set_timer(HPETState *h,
     uint64_t tn_cmp, cur_tick, diff;
 
     ASSERT(tn < HPET_TIMER_NUM);
-    
+    ASSERT(spin_is_locked(&h->lock));
+
     if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
         return;
 
@@ -212,6 +220,8 @@ static void hpet_write(
 
     if ( hpet_check_access_length(addr, length) != 0 )
         return;
+
+    spin_lock(&h->lock);
 
     old_val = hpet_read64(h, addr & ~7);
     if ( (addr & ~7) == HPET_COUNTER )
@@ -302,6 +312,8 @@ static void hpet_write(
         /* Ignore writes to unsupported and reserved registers. */
         break;
     }
+
+    spin_unlock(&h->lock);
 }
 
 static int hpet_range(struct vcpu *v, unsigned long addr)
@@ -320,6 +332,8 @@ static void hpet_route_interrupt(HPETSta
 {
     unsigned int tn_int_route = timer_int_route(h, tn);
     struct domain *d = h->vcpu->domain;
+
+    ASSERT(spin_is_locked(&h->lock));
 
     if ( (tn <= 1) && (h->hpet.config & HPET_CFG_LEGACY) )
     {
@@ -352,8 +366,13 @@ static void hpet_timer_fn(void *opaque)
     HPETState *h = htfi->hs;
     unsigned int tn = htfi->tn;
 
+    spin_lock(&h->lock);
+
     if ( !hpet_enabled(h) || !timer_enabled(h, tn) )
-        return;
+    {
+        spin_unlock(&h->lock);
+        return;
+    }
 
     hpet_route_interrupt(h, tn);
 
@@ -374,6 +393,8 @@ static void hpet_timer_fn(void *opaque)
         set_timer(&h->timers[tn], 
                   NOW() + hpet_tick_to_ns(h, h->hpet.period[tn]));
     }
+
+    spin_unlock(&h->lock);
 }
 
 void hpet_migrate_timers(struct vcpu *v)
@@ -391,12 +412,19 @@ static int hpet_save(struct domain *d, h
 static int hpet_save(struct domain *d, hvm_domain_context_t *h)
 {
     HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
+    int rc;
+
+    spin_lock(&hp->lock);
 
     /* Write the proper value into the main counter */
     hp->hpet.mc64 = hp->mc_offset + guest_time_hpet(hp->vcpu);
 
     /* Save the HPET registers */
-    return hvm_save_entry(HPET, 0, h, &hp->hpet);
+    rc = hvm_save_entry(HPET, 0, h, &hp->hpet);
+
+    spin_unlock(&hp->lock);
+
+    return rc;
 }
 
 static int hpet_load(struct domain *d, hvm_domain_context_t *h)
@@ -404,9 +432,14 @@ static int hpet_load(struct domain *d, h
     HPETState *hp = &d->arch.hvm_domain.pl_time.vhpet;
     int i;
 
+    spin_lock(&hp->lock);
+
     /* Reload the HPET registers */
     if ( hvm_load_entry(HPET, h, &hp->hpet) )
+    {
+        spin_unlock(&hp->lock);
         return -EINVAL;
+    }
     
     /* Recalculate the offset between the main counter and guest time */
     hp->mc_offset = hp->hpet.mc64 - guest_time_hpet(hp->vcpu);
@@ -415,6 +448,8 @@ static int hpet_load(struct domain *d, h
     for ( i = 0; i < HPET_TIMER_NUM; i++ )
         hpet_set_timer(hp, i);
 
+    spin_unlock(&hp->lock);
+
     return 0;
 }
 
@@ -426,6 +461,8 @@ void hpet_init(struct vcpu *v)
     int i;
 
     memset(h, 0, sizeof(HPETState));
+
+    spin_lock_init(&h->lock);
 
     h->vcpu = v;
     h->tsc_freq = ticks_per_sec(v);
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Fri Jun 15 15:30:49 2007 +0100
@@ -401,6 +401,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
         get_ioreq(v)->vp_eport = v->arch.hvm_vcpu.xen_port;
     spin_unlock(&v->domain->arch.hvm_domain.ioreq.lock);
 
+    spin_lock_init(&v->arch.hvm_vcpu.tm_lock);
     INIT_LIST_HEAD(&v->arch.hvm_vcpu.tm_list);
 
     if ( v->vcpu_id == 0 )
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/i8254.c  Fri Jun 15 15:30:49 2007 +0100
@@ -82,6 +82,8 @@ static int pit_get_count(PITState *pit, 
     struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
     struct vcpu *v = vpit_vcpu(pit);
 
+    ASSERT(spin_is_locked(&pit->lock));
+
     d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
                  PIT_FREQ, ticks_per_sec(v));
 
@@ -111,6 +113,8 @@ static int pit_get_out(PITState *pit, in
     int out;
     struct vcpu *v = vpit_vcpu(pit);
 
+    ASSERT(spin_is_locked(&pit->lock));
+
     d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], 
                  PIT_FREQ, ticks_per_sec(v));
 
@@ -142,6 +146,8 @@ static void pit_set_gate(PITState *pit, 
 {
     struct hvm_hw_pit_channel *s = &pit->hw.channels[channel];
     struct vcpu *v = vpit_vcpu(pit);
+
+    ASSERT(spin_is_locked(&pit->lock));
 
     switch ( s->mode )
     {
@@ -165,6 +171,7 @@ static void pit_set_gate(PITState *pit, 
 
 int pit_get_gate(PITState *pit, int channel)
 {
+    ASSERT(spin_is_locked(&pit->lock));
     return pit->hw.channels[channel].gate;
 }
 
@@ -181,10 +188,15 @@ static void pit_load_count(PITState *pit
     struct periodic_time *pt = &pit->pt[channel];
     struct vcpu *v = vpit_vcpu(pit);
 
+    ASSERT(spin_is_locked(&pit->lock));
+
     if ( val == 0 )
         val = 0x10000;
 
-    pit->count_load_time[channel] = hvm_get_guest_time(pt->vcpu);
+    if ( v == NULL )
+        rdtscll(pit->count_load_time[channel]);
+    else
+        pit->count_load_time[channel] = hvm_get_guest_time(v);
     s->count = val;
     period = DIV_ROUND((val * 1000000000ULL), PIT_FREQ);
 
@@ -209,23 +221,29 @@ static void pit_load_count(PITState *pit
     }
 }
 
-static void pit_latch_count(PITState *s, int channel)
-{
-    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
+static void pit_latch_count(PITState *pit, int channel)
+{
+    struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
+
+    ASSERT(spin_is_locked(&pit->lock));
+
     if ( !c->count_latched )
     {
-        c->latched_count = pit_get_count(s, channel);
+        c->latched_count = pit_get_count(pit, channel);
         c->count_latched = c->rw_mode;
     }
 }
 
-static void pit_latch_status(PITState *s, int channel)
-{
-    struct hvm_hw_pit_channel *c = &s->hw.channels[channel];
+static void pit_latch_status(PITState *pit, int channel)
+{
+    struct hvm_hw_pit_channel *c = &pit->hw.channels[channel];
+
+    ASSERT(spin_is_locked(&pit->lock));
+
     if ( !c->status_latched )
     {
         /* TODO: Return NULL COUNT (bit 6). */
-        c->status = ((pit_get_out(s, channel) << 7) |
+        c->status = ((pit_get_out(pit, channel) << 7) |
                      (c->rw_mode << 4) |
                      (c->mode << 1) |
                      c->bcd);
@@ -240,6 +258,8 @@ static void pit_ioport_write(struct PITS
 
     val  &= 0xff;
     addr &= 3;
+
+    spin_lock(&pit->lock);
 
     if ( addr == 3 )
     {
@@ -304,6 +324,8 @@ static void pit_ioport_write(struct PITS
             break;
         }
     }
+
+    spin_unlock(&pit->lock);
 }
 
 static uint32_t pit_ioport_read(struct PITState *pit, uint32_t addr)
@@ -313,6 +335,8 @@ static uint32_t pit_ioport_read(struct P
     
     addr &= 3;
     s = &pit->hw.channels[addr];
+
+    spin_lock(&pit->lock);
 
     if ( s->status_latched )
     {
@@ -364,12 +388,16 @@ static uint32_t pit_ioport_read(struct P
         }
     }
 
+    spin_unlock(&pit->lock);
+
     return ret;
 }
 
 void pit_stop_channel0_irq(PITState *pit)
 {
+    spin_lock(&pit->lock);
     destroy_periodic_time(&pit->pt[0]);
+    spin_unlock(&pit->lock);
 }
 
 #ifdef HVM_DEBUG_SUSPEND
@@ -422,11 +450,18 @@ static int pit_save(struct domain *d, hv
 static int pit_save(struct domain *d, hvm_domain_context_t *h)
 {
     PITState *pit = domain_vpit(d);
+    int rc;
+
+    spin_lock(&pit->lock);
     
     pit_info(pit);
 
     /* Save the PIT hardware state */
-    return hvm_save_entry(PIT, 0, h, &pit->hw);
+    rc = hvm_save_entry(PIT, 0, h, &pit->hw);
+
+    spin_unlock(&pit->lock);
+
+    return rc;
 }
 
 static int pit_load(struct domain *d, hvm_domain_context_t *h)
@@ -434,9 +469,14 @@ static int pit_load(struct domain *d, hv
     PITState *pit = domain_vpit(d);
     int i;
 
+    spin_lock(&pit->lock);
+
     /* Restore the PIT hardware state */
     if ( hvm_load_entry(PIT, h, &pit->hw) )
+    {
+        spin_unlock(&pit->lock);
         return 1;
+    }
     
     /* Recreate platform timers from hardware state.  There will be some 
      * time jitter here, but the wall-clock will have jumped massively, so 
@@ -448,6 +488,9 @@ static int pit_load(struct domain *d, hv
     }
 
     pit_info(pit);
+
+    spin_unlock(&pit->lock);
+
     return 0;
 }
 
@@ -456,17 +499,15 @@ void pit_init(struct vcpu *v, unsigned l
 void pit_init(struct vcpu *v, unsigned long cpu_khz)
 {
     PITState *pit = vcpu_vpit(v);
-    struct periodic_time *pt;
     struct hvm_hw_pit_channel *s;
     int i;
 
-    pt = &pit->pt[0];  
-    pt[0].vcpu = v;
-    pt[1].vcpu = v;
-    pt[2].vcpu = v;
+    spin_lock_init(&pit->lock);
+
+    /* Some sub-functions assert that they are called with the lock held. */
+    spin_lock(&pit->lock);
 
     register_portio_handler(v->domain, PIT_BASE, 4, handle_pit_io);
-    /* register the speaker port */
     register_portio_handler(v->domain, 0x61, 1, handle_speaker_io);
     ticks_per_sec(v) = cpu_khz * (int64_t)1000;
 
@@ -477,6 +518,8 @@ void pit_init(struct vcpu *v, unsigned l
         s->gate = (i != 2);
         pit_load_count(pit, i, 0);
     }
+
+    spin_unlock(&pit->lock);
 }
 
 void pit_deinit(struct domain *d)
@@ -492,10 +535,10 @@ static int handle_pit_io(ioreq_t *p)
 
     if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
     {
-        gdprintk(XENLOG_WARNING, "HVM_PIT bad access\n");
+        gdprintk(XENLOG_WARNING, "PIT bad access\n");
         return 1;
     }
-    
+
     if ( p->dir == IOREQ_WRITE )
     {
         pit_ioport_write(vpit, p->addr, p->data);
@@ -505,7 +548,7 @@ static int handle_pit_io(ioreq_t *p)
         if ( (p->addr & 3) != 3 )
             p->data = pit_ioport_read(vpit, p->addr);
         else
-            gdprintk(XENLOG_WARNING, "HVM_PIT: read A1:A0=3!\n");
+            gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n");
     }
 
     return 1;
@@ -533,14 +576,18 @@ static int handle_speaker_io(ioreq_t *p)
 
     if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
     {
-        gdprintk(XENLOG_WARNING, "HVM_SPEAKER bad access\n");
+        gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n");
         return 1;
     }
+
+    spin_lock(&vpit->lock);
 
     if ( p->dir == IOREQ_WRITE )
         speaker_ioport_write(vpit, p->addr, p->data);
     else
         p->data = speaker_ioport_read(vpit, p->addr);
+
+    spin_unlock(&vpit->lock);
 
     return 1;
 }
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/pmtimer.c
--- a/xen/arch/x86/hvm/pmtimer.c        Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/pmtimer.c        Fri Jun 15 15:30:49 2007 +0100
@@ -53,6 +53,8 @@
 /* Dispatch SCIs based on the PM1a_STS and PM1a_EN registers */
 static void pmt_update_sci(PMTState *s)
 {
+    ASSERT(spin_is_locked(&s->lock));
+
     if ( s->pm.pm1a_en & s->pm.pm1a_sts & SCI_MASK )
         hvm_isa_irq_assert(s->vcpu->domain, SCI_IRQ);
     else
@@ -66,6 +68,8 @@ static void pmt_update_time(PMTState *s)
     uint64_t curr_gtime;
     uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB;
     
+    ASSERT(spin_is_locked(&s->lock));
+
     /* Update the timer */
     curr_gtime = hvm_get_guest_time(s->vcpu);
     s->pm.tmr_val += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
@@ -89,6 +93,8 @@ static void pmt_timer_callback(void *opa
     uint32_t pmt_cycles_until_flip;
     uint64_t time_until_flip;
 
+    spin_lock(&s->lock);
+
     /* Recalculate the timer and make sure we get an SCI if we need one */
     pmt_update_time(s);
 
@@ -103,8 +109,9 @@ static void pmt_timer_callback(void *opa
 
     /* Wake up again near the next bit-flip */
     set_timer(&s->timer, NOW() + time_until_flip + MILLISECS(1));
-}
-
+
+    spin_unlock(&s->lock);
+}
 
 /* Handle port I/O to the PM1a_STS and PM1a_EN registers */
 static int handle_evt_io(ioreq_t *p)
@@ -114,7 +121,9 @@ static int handle_evt_io(ioreq_t *p)
     uint32_t addr, data, byte;
     int i;
 
-    if ( p->dir == 0 ) /* Write */
+    spin_lock(&s->lock);
+
+    if ( p->dir == IOREQ_WRITE )
     {
         /* Handle this I/O one byte at a time */
         for ( i = p->size, addr = p->addr, data = p->data;
@@ -122,7 +131,7 @@ static int handle_evt_io(ioreq_t *p)
               i--, addr++, data >>= 8 )
         {
             byte = data & 0xff;
-            switch(addr) 
+            switch ( addr )
             {
                 /* PM1a_STS register bits are write-to-clear */
             case PM1a_STS_ADDR:
@@ -149,7 +158,7 @@ static int handle_evt_io(ioreq_t *p)
         /* Fix up the SCI state to match the new register state */
         pmt_update_sci(s);
     }
-    else /* Read */
+    else /* p->dir == IOREQ_READ */
     {
         data = s->pm.pm1a_sts | (((uint32_t) s->pm.pm1a_en) << 16);
         data >>= 8 * (p->addr - PM1a_STS_ADDR);
@@ -157,6 +166,9 @@ static int handle_evt_io(ioreq_t *p)
         else if ( p->size == 2 ) data &= 0xffff;
         p->data = data;
     }
+
+    spin_unlock(&s->lock);
+
     return 1;
 }
 
@@ -167,29 +179,31 @@ static int handle_pmt_io(ioreq_t *p)
     struct vcpu *v = current;
     PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
 
-    if (p->size != 4 ||
-        p->data_is_ptr ||
-        p->type != IOREQ_TYPE_PIO){
-        printk("HVM_PMT: wrong PM timer IO\n");
+    if ( (p->size != 4) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    {
+        gdprintk(XENLOG_WARNING, "HVM_PMT bad access\n");
         return 1;
     }
     
-    if (p->dir == 0) { /* write */
-        /* PM_TMR_BLK is read-only */
-        return 1;
-    } else if (p->dir == 1) { /* read */
+    if ( p->dir == IOREQ_READ )
+    {
+        spin_lock(&s->lock);
         pmt_update_time(s);
         p->data = s->pm.tmr_val;
+        spin_unlock(&s->lock);
         return 1;
     }
+
     return 0;
 }
 
 static int pmtimer_save(struct domain *d, hvm_domain_context_t *h)
 {
     PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
-    uint32_t msb = s->pm.tmr_val & TMR_VAL_MSB;
-    uint32_t x;
+    uint32_t x, msb = s->pm.tmr_val & TMR_VAL_MSB;
+    int rc;
+
+    spin_lock(&s->lock);
 
     /* Update the counter to the guest's current time.  We always save
      * with the domain paused, so the saved time should be after the
@@ -202,22 +216,33 @@ static int pmtimer_save(struct domain *d
     /* No point in setting the SCI here because we'll already have saved the 
      * IRQ and *PIC state; we'll fix it up when we restore the domain */
 
-    return hvm_save_entry(PMTIMER, 0, h, &s->pm);
+    rc = hvm_save_entry(PMTIMER, 0, h, &s->pm);
+
+    spin_unlock(&s->lock);
+
+    return rc;
 }
 
 static int pmtimer_load(struct domain *d, hvm_domain_context_t *h)
 {
     PMTState *s = &d->arch.hvm_domain.pl_time.vpmt;
+
+    spin_lock(&s->lock);
 
     /* Reload the registers */
     if ( hvm_load_entry(PMTIMER, h, &s->pm) )
+    {
+        spin_unlock(&s->lock);
         return -EINVAL;
+    }
 
     /* Calculate future counter values from now. */
     s->last_gtime = hvm_get_guest_time(s->vcpu);
 
     /* Set the SCI state from the registers */ 
     pmt_update_sci(s);
+
+    spin_unlock(&s->lock);
     
     return 0;
 }
@@ -225,14 +250,11 @@ HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtim
 HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, 
                           1, HVMSR_PER_DOM);
 
-
 void pmtimer_init(struct vcpu *v)
 {
     PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
 
-    s->pm.tmr_val = 0;
-    s->pm.pm1a_sts = 0;
-    s->pm.pm1a_en = 0;
+    spin_lock_init(&s->lock);
 
     s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v);
     s->vcpu = v;
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/rtc.c    Fri Jun 15 15:30:49 2007 +0100
@@ -34,10 +34,12 @@
                                        arch.hvm_domain.pl_time.vrtc))
 #define vrtc_vcpu(rtc)   (vrtc_domain(rtc)->vcpu[0])
 
-void rtc_periodic_cb(struct vcpu *v, void *opaque)
+static void rtc_periodic_cb(struct vcpu *v, void *opaque)
 {
     RTCState *s = opaque;
+    spin_lock(&s->lock);
     s->hw.cmos_data[RTC_REG_C] |= 0xc0;
+    spin_unlock(&s->lock);
 }
 
 int is_rtc_periodic_irq(void *opaque)
@@ -54,6 +56,8 @@ static void rtc_timer_update(RTCState *s
 {
     int period_code, period;
     struct vcpu *v = vrtc_vcpu(s);
+
+    ASSERT(spin_is_locked(&s->lock));
 
     period_code = s->hw.cmos_data[RTC_REG_A] & RTC_RATE_SELECT;
     if ( (period_code != 0) && (s->hw.cmos_data[RTC_REG_B] & RTC_PIE) )
@@ -78,14 +82,21 @@ static int rtc_ioport_write(void *opaque
 {
     RTCState *s = opaque;
 
+    spin_lock(&s->lock);
+
     if ( (addr & 1) == 0 )
     {
-        s->hw.cmos_index = data & 0x7f;
-        return (s->hw.cmos_index < RTC_CMOS_SIZE);
+        data &= 0x7f;
+        s->hw.cmos_index = data;
+        spin_unlock(&s->lock);
+        return (data < RTC_CMOS_SIZE);
     }
 
     if ( s->hw.cmos_index >= RTC_CMOS_SIZE )
+    {
+        spin_unlock(&s->lock);
         return 0;
+    }
 
     switch ( s->hw.cmos_index )
     {
@@ -134,6 +145,8 @@ static int rtc_ioport_write(void *opaque
         break;
     }
 
+    spin_unlock(&s->lock);
+
     return 1;
 }
 
@@ -158,6 +171,8 @@ static void rtc_set_time(RTCState *s)
     struct tm *tm = &s->current_tm;
     unsigned long before, after; /* XXX s_time_t */
       
+    ASSERT(spin_is_locked(&s->lock));
+
     before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
                    tm->tm_hour, tm->tm_min, tm->tm_sec);
     
@@ -182,6 +197,8 @@ static void rtc_copy_date(RTCState *s)
     const struct tm *tm = &s->current_tm;
     struct domain *d = vrtc_domain(s);
 
+    ASSERT(spin_is_locked(&s->lock));
+
     if ( s->time_offset_seconds != d->time_offset_seconds )
     {
         s->current_tm = gmtime(get_localtime(d));
@@ -230,6 +247,8 @@ static void rtc_next_second(RTCState *s)
     struct tm *tm = &s->current_tm;
     int days_in_month;
     struct domain *d = vrtc_domain(s);
+
+    ASSERT(spin_is_locked(&s->lock));
 
     if ( s->time_offset_seconds != d->time_offset_seconds )
     {
@@ -279,6 +298,8 @@ static void rtc_update_second(void *opaq
 {
     RTCState *s = opaque;
 
+    spin_lock(&s->lock);
+
     /* if the oscillator is not in normal operation, we do not update */
     if ( (s->hw.cmos_data[RTC_REG_A] & RTC_DIV_CTL) != RTC_REF_CLCK_32KHZ )
     {
@@ -295,12 +316,16 @@ static void rtc_update_second(void *opaq
         /* Delay time before update cycle */
         set_timer(&s->second_timer2, s->next_second_time + 244000);
     }
+
+    spin_unlock(&s->lock);
 }
 
 static void rtc_update_second2(void *opaque)
 {
     RTCState *s = opaque;
     struct domain *d = vrtc_domain(s);
+
+    spin_lock(&s->lock);
 
     if ( !(s->hw.cmos_data[RTC_REG_B] & RTC_SET) )
         rtc_copy_date(s);
@@ -337,15 +362,18 @@ static void rtc_update_second2(void *opa
 
     s->next_second_time += 1000000000ULL;
     set_timer(&s->second_timer, s->next_second_time);
-}
-
-static uint32_t rtc_ioport_read(void *opaque, uint32_t addr)
-{
-    RTCState *s = opaque;
+
+    spin_unlock(&s->lock);
+}
+
+static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
+{
     int ret;
 
     if ( (addr & 1) == 0 )
         return 0xff;
+
+    spin_lock(&s->lock);
 
     switch ( s->hw.cmos_index )
     {
@@ -371,6 +399,8 @@ static uint32_t rtc_ioport_read(void *op
         break;
     }
 
+    spin_unlock(&s->lock);
+
     return ret;
 }
 
@@ -413,7 +443,11 @@ static int rtc_save(struct domain *d, hv
 static int rtc_save(struct domain *d, hvm_domain_context_t *h)
 {
     RTCState *s = domain_vrtc(d);
-    return hvm_save_entry(RTC, 0, h, &s->hw);
+    int rc;
+    spin_lock(&s->lock);
+    rc = hvm_save_entry(RTC, 0, h, &s->hw);
+    spin_unlock(&s->lock);
+    return rc;
 }
 
 /* Reload the hardware state from a saved domain */
@@ -421,9 +455,14 @@ static int rtc_load(struct domain *d, hv
 {
     RTCState *s = domain_vrtc(d);
 
+    spin_lock(&s->lock);
+
     /* Restore the registers */
     if ( hvm_load_entry(RTC, h, &s->hw) != 0 )
+    {
+        spin_unlock(&s->lock);
         return -EINVAL;
+    }
 
     /* Reset the wall-clock time.  In normal running, this runs with host 
      * time, so let's keep doing that. */
@@ -436,6 +475,8 @@ static int rtc_load(struct domain *d, hv
     /* Reset the periodic interrupt timer based on the registers */
     rtc_timer_update(s);
 
+    spin_unlock(&s->lock);
+
     return 0;
 }
 
@@ -445,6 +486,8 @@ void rtc_init(struct vcpu *v, int base)
 void rtc_init(struct vcpu *v, int base)
 {
     RTCState *s = vcpu_vrtc(v);
+
+    spin_lock_init(&s->lock);
 
     s->hw.cmos_data[RTC_REG_A] = RTC_REF_CLCK_32KHZ | 6; /* ~1kHz */
     s->hw.cmos_data[RTC_REG_B] = RTC_24H;
@@ -452,7 +495,10 @@ void rtc_init(struct vcpu *v, int base)
     s->hw.cmos_data[RTC_REG_D] = RTC_VRT;
 
     s->current_tm = gmtime(get_localtime(v->domain));
+
+    spin_lock(&s->lock);
     rtc_copy_date(s);
+    spin_unlock(&s->lock);
 
     init_timer(&s->second_timer, rtc_update_second, s, v->processor);
     init_timer(&s->second_timer2, rtc_update_second2, s, v->processor);
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c    Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/arch/x86/hvm/vpt.c    Fri Jun 15 15:30:49 2007 +0100
@@ -17,11 +17,31 @@
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  *
  */
+
 #include <xen/time.h>
 #include <asm/hvm/support.h>
 #include <asm/hvm/vpt.h>
 #include <asm/event.h>
 
+static void pt_lock(struct periodic_time *pt)
+{
+    struct vcpu *v;
+
+    for ( ; ; )
+    {
+        v = pt->vcpu;
+        spin_lock(&v->arch.hvm_vcpu.tm_lock);
+        if ( likely(pt->vcpu == v) )
+            break;
+        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+    }
+}
+
+static void pt_unlock(struct periodic_time *pt)
+{
+    spin_unlock(&pt->vcpu->arch.hvm_vcpu.tm_lock);
+}
+
 static void missed_ticks(struct periodic_time *pt)
 {
     s_time_t missed_ticks;
@@ -52,16 +72,22 @@ void pt_freeze_time(struct vcpu *v)
     if ( test_bit(_VPF_blocked, &v->pause_flags) )
         return;
 
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+
     v->arch.hvm_vcpu.guest_time = hvm_get_guest_time(v);
 
     list_for_each_entry ( pt, head, list )
         stop_timer(&pt->timer);
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
 
 void pt_thaw_time(struct vcpu *v)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
     if ( v->arch.hvm_vcpu.guest_time )
     {
@@ -74,11 +100,15 @@ void pt_thaw_time(struct vcpu *v)
             set_timer(&pt->timer, pt->scheduled);
         }
     }
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
 
 static void pt_timer_fn(void *data)
 {
     struct periodic_time *pt = data;
+
+    pt_lock(pt);
 
     pt->pending_intr_nr++;
     pt->scheduled += pt->period;
@@ -89,6 +119,8 @@ static void pt_timer_fn(void *data)
         set_timer(&pt->timer, pt->scheduled);
 
     vcpu_kick(pt->vcpu);
+
+    pt_unlock(pt);
 }
 
 void pt_update_irq(struct vcpu *v)
@@ -98,6 +130,8 @@ void pt_update_irq(struct vcpu *v)
     uint64_t max_lag = -1ULL;
     int irq = -1;
 
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+
     list_for_each_entry ( pt, head, list )
     {
         if ( !is_isa_irq_masked(v, pt->irq) && pt->pending_intr_nr &&
@@ -108,6 +142,8 @@ void pt_update_irq(struct vcpu *v)
         }
     }
 
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+
     if ( is_lvtt(v, irq) )
     {
         vlapic_set_irq(vcpu_vlapic(v), irq, 0);
@@ -119,7 +155,7 @@ void pt_update_irq(struct vcpu *v)
     }
 }
 
-struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
+static struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
@@ -152,25 +188,42 @@ struct periodic_time *is_pt_irq(struct v
 
 void pt_intr_post(struct vcpu *v, int vector, int type)
 {
-    struct periodic_time *pt = is_pt_irq(v, vector, type);
-
+    struct periodic_time *pt;
+    time_cb *cb;
+    void *cb_priv;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+
+    pt = is_pt_irq(v, vector, type);
     if ( pt == NULL )
-        return;
+    {
+        spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+        return;
+    }
+
+    ASSERT(pt->vcpu == v);
 
     pt->pending_intr_nr--;
     pt->last_plt_gtime += pt->period_cycles;
 
-    if ( hvm_get_guest_time(pt->vcpu) < pt->last_plt_gtime )
-        hvm_set_guest_time(pt->vcpu, pt->last_plt_gtime);
-
-    if ( pt->cb != NULL )
-        pt->cb(pt->vcpu, pt->priv);
+    if ( hvm_get_guest_time(v) < pt->last_plt_gtime )
+        hvm_set_guest_time(v, pt->last_plt_gtime);
+
+    cb = pt->cb;
+    cb_priv = pt->priv;
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+
+    if ( cb != NULL )
+        cb(v, cb_priv);
 }
 
 void pt_reset(struct vcpu *v)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
     list_for_each_entry ( pt, head, list )
     {
@@ -182,18 +235,24 @@ void pt_reset(struct vcpu *v)
             set_timer(&pt->timer, pt->scheduled);
         }
     }
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
 
 void pt_migrate(struct vcpu *v)
 {
     struct list_head *head = &v->arch.hvm_vcpu.tm_list;
     struct periodic_time *pt;
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
     list_for_each_entry ( pt, head, list )
     {
         if ( pt->enabled )
             migrate_timer(&pt->timer, v->processor);
     }
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
 
 void create_periodic_time(
@@ -201,6 +260,8 @@ void create_periodic_time(
     uint8_t irq, char one_shot, time_cb *cb, void *data)
 {
     destroy_periodic_time(pt);
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
 
     init_timer(&pt->timer, pt_timer_fn, pt, v->processor);
     pt->enabled = 1;
@@ -223,6 +284,8 @@ void create_periodic_time(
 
     list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
     set_timer(&pt->timer, pt->scheduled);
+
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
 }
 
 void destroy_periodic_time(struct periodic_time *pt)
@@ -230,8 +293,10 @@ void destroy_periodic_time(struct period
     if ( !pt->enabled )
         return;
 
+    pt_lock(pt);
     pt->enabled = 0;
     pt->pending_intr_nr = 0;
     list_del(&pt->list);
     kill_timer(&pt->timer);
-}
+    pt_unlock(pt);
+}
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/common/timer.c
--- a/xen/common/timer.c        Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/common/timer.c        Fri Jun 15 15:30:49 2007 +0100
@@ -183,7 +183,7 @@ static inline void timer_lock(struct tim
 
 static inline void timer_unlock(struct timer *timer)
 {
-        spin_unlock(&per_cpu(timers, timer->cpu).lock);
+    spin_unlock(&per_cpu(timers, timer->cpu).lock);
 }
 
 #define timer_unlock_irq(t) \
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/include/asm-x86/hvm/vcpu.h
--- a/xen/include/asm-x86/hvm/vcpu.h    Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/include/asm-x86/hvm/vcpu.h    Fri Jun 15 15:30:49 2007 +0100
@@ -35,6 +35,9 @@ struct hvm_vcpu {
     struct vlapic       vlapic;
     s64                 cache_tsc_offset;
     u64                 guest_time;
+
+    /* Lock and list for virtual platform timers. */
+    spinlock_t          tm_lock;
     struct list_head    tm_list;
 
     /* For AP startup */
diff -r f1ba2e652724 -r 8ad38aaaeb89 xen/include/asm-x86/hvm/vpt.h
--- a/xen/include/asm-x86/hvm/vpt.h     Fri Jun 15 11:50:54 2007 +0100
+++ b/xen/include/asm-x86/hvm/vpt.h     Fri Jun 15 15:30:49 2007 +0100
@@ -31,7 +31,6 @@
 #include <asm/hvm/vpic.h>
 #include <public/hvm/save.h>
 
-
 struct HPETState;
 struct HPET_timer_fn_info {
     struct HPETState       *hs;
@@ -45,6 +44,7 @@ typedef struct HPETState {
     uint64_t mc_offset;
     struct timer timers[HPET_TIMER_NUM];
     struct HPET_timer_fn_info timer_fn_info[HPET_TIMER_NUM]; 
+    spinlock_t lock;
 } HPETState;
 
 
@@ -80,6 +80,7 @@ typedef struct PITState {
     int64_t count_load_time[3];
     /* irq handling */
     struct periodic_time pt[3];
+    spinlock_t lock;
 } PITState;
 
 typedef struct RTCState {
@@ -93,6 +94,7 @@ typedef struct RTCState {
     struct timer second_timer2;
     struct periodic_time pt;
     int32_t time_offset_seconds;
+    spinlock_t lock;
 } RTCState;
 
 #define FREQUENCE_PMTIMER  3579545  /* Timer should run at 3.579545 MHz */
@@ -102,6 +104,7 @@ typedef struct PMTState {
     uint64_t last_gtime;        /* Last (guest) time we updated the timer */
     uint64_t scale;             /* Multiplier to get from tsc to timer ticks */
     struct timer timer;         /* To make sure we send SCIs */
+    spinlock_t lock;
 } PMTState;
 
 struct pl_time {    /* platform time */
@@ -116,7 +119,6 @@ void pt_freeze_time(struct vcpu *v);
 void pt_freeze_time(struct vcpu *v);
 void pt_thaw_time(struct vcpu *v);
 void pt_update_irq(struct vcpu *v);
-struct periodic_time *is_pt_irq(struct vcpu *v, int vector, int type);
 void pt_intr_post(struct vcpu *v, int vector, int type);
 void pt_reset(struct vcpu *v);
 void pt_migrate(struct vcpu *v);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm: Add locking to platform timers., Xen patchbot-unstable <=