ia64/xen-unstable

changeset 17764:6e688d5a936b

x86: i8254 device model is shared between PV and HVM guests, so must
take care not to run hvm_get_guest_time() on a PV VCPU. The spinlock
is not initialised and spin_lock() can thus spin forever.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri May 30 19:31:18 2008 +0100 (2008-05-30)
parents 487dc63f95ff
children 85fa199b4b7b
files xen/arch/x86/hvm/i8254.c xen/arch/x86/hvm/vpt.c
line diff
     1.1 --- a/xen/arch/x86/hvm/i8254.c	Fri May 30 16:44:13 2008 +0100
     1.2 +++ b/xen/arch/x86/hvm/i8254.c	Fri May 30 19:31:18 2008 +0100
     1.3 @@ -54,6 +54,9 @@ static int handle_pit_io(
     1.4  static int handle_speaker_io(
     1.5      int dir, uint32_t port, uint32_t bytes, uint32_t *val);
     1.6  
     1.7 +#define get_guest_time(v) \
     1.8 +   (is_hvm_vcpu(v) ? hvm_get_guest_time(v) : (u64)get_s_time())
     1.9 +
    1.10  /* Compute with 96 bit intermediate result: (a*b)/c */
    1.11  static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
    1.12  {
    1.13 @@ -87,7 +90,7 @@ static int pit_get_count(PITState *pit, 
    1.14  
    1.15      ASSERT(spin_is_locked(&pit->lock));
    1.16  
    1.17 -    d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel],
    1.18 +    d = muldiv64(get_guest_time(v) - pit->count_load_time[channel],
    1.19                   PIT_FREQ, SYSTEM_TIME_HZ);
    1.20  
    1.21      switch ( c->mode )
    1.22 @@ -118,7 +121,7 @@ static int pit_get_out(PITState *pit, in
    1.23  
    1.24      ASSERT(spin_is_locked(&pit->lock));
    1.25  
    1.26 -    d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], 
    1.27 +    d = muldiv64(get_guest_time(v) - pit->count_load_time[channel], 
    1.28                   PIT_FREQ, SYSTEM_TIME_HZ);
    1.29  
    1.30      switch ( s->mode )
    1.31 @@ -165,7 +168,7 @@ static void pit_set_gate(PITState *pit, 
    1.32      case 3:
    1.33          /* Restart counting on rising edge. */
    1.34          if ( s->gate < val )
    1.35 -            pit->count_load_time[channel] = hvm_get_guest_time(v);
    1.36 +            pit->count_load_time[channel] = get_guest_time(v);
    1.37          break;
    1.38      }
    1.39  
    1.40 @@ -181,7 +184,7 @@ int pit_get_gate(PITState *pit, int chan
    1.41  static void pit_time_fired(struct vcpu *v, void *priv)
    1.42  {
    1.43      uint64_t *count_load_time = priv;
    1.44 -    *count_load_time = hvm_get_guest_time(v);
    1.45 +    *count_load_time = get_guest_time(v);
    1.46  }
    1.47  
    1.48  static void pit_load_count(PITState *pit, int channel, int val)
    1.49 @@ -198,7 +201,7 @@ static void pit_load_count(PITState *pit
    1.50      if ( v == NULL )
    1.51          pit->count_load_time[channel] = 0;
    1.52      else
    1.53 -        pit->count_load_time[channel] = hvm_get_guest_time(v);
    1.54 +        pit->count_load_time[channel] = get_guest_time(v);
    1.55      s->count = val;
    1.56      period = DIV_ROUND(val * SYSTEM_TIME_HZ, PIT_FREQ);
    1.57  
    1.58 @@ -436,7 +439,7 @@ static int pit_load(struct domain *d, hv
    1.59       * time jitter here, but the wall-clock will have jumped massively, so 
    1.60       * we hope the guest can handle it.
    1.61       */
    1.62 -    pit->pt0.last_plt_gtime = hvm_get_guest_time(d->vcpu[0]);
    1.63 +    pit->pt0.last_plt_gtime = get_guest_time(d->vcpu[0]);
    1.64      for ( i = 0; i < 3; i++ )
    1.65          pit_load_count(pit, i, pit->hw.channels[i].count);
    1.66  
     2.1 --- a/xen/arch/x86/hvm/vpt.c	Fri May 30 16:44:13 2008 +0100
     2.2 +++ b/xen/arch/x86/hvm/vpt.c	Fri May 30 19:31:18 2008 +0100
     2.3 @@ -39,6 +39,9 @@ u64 hvm_get_guest_time(struct vcpu *v)
     2.4      struct pl_time *pl = &v->domain->arch.hvm_domain.pl_time;
     2.5      u64 now;
     2.6  
     2.7 +    /* Called from device models shared with PV guests. Be careful. */
     2.8 +    ASSERT(is_hvm_vcpu(v));
     2.9 +
    2.10      spin_lock(&pl->pl_time_lock);
    2.11      now = get_s_time() + pl->stime_offset;
    2.12      if ( (int64_t)(now - pl->last_guest_time) >= 0 )