diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2008-05-30 19:31:18 +0100 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2008-05-30 19:31:18 +0100 |
commit | 5024576315ef4c1629510efe73ef777ef0868ec7 (patch) | |
tree | fd614f2a83ca1b18b8d61467bca99a3d08e9a8a2 | |
parent | 8d4e5d626a533220ecf66b6fe88e2179a42d6b48 (diff) | |
download | xen-5024576315ef4c1629510efe73ef777ef0868ec7.tar.gz xen-5024576315ef4c1629510efe73ef777ef0868ec7.tar.bz2 xen-5024576315ef4c1629510efe73ef777ef0868ec7.zip |
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>
-rw-r--r-- | xen/arch/x86/hvm/i8254.c | 15 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vpt.c | 3 |
2 files changed, 12 insertions, 6 deletions
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index 090dbf7193..6fa955cad6 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -54,6 +54,9 @@ static int handle_pit_io( static int handle_speaker_io( int dir, uint32_t port, uint32_t bytes, uint32_t *val); +#define get_guest_time(v) \ + (is_hvm_vcpu(v) ? hvm_get_guest_time(v) : (u64)get_s_time()) + /* Compute with 96 bit intermediate result: (a*b)/c */ static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { @@ -87,7 +90,7 @@ static int pit_get_count(PITState *pit, int channel) ASSERT(spin_is_locked(&pit->lock)); - d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], + d = muldiv64(get_guest_time(v) - pit->count_load_time[channel], PIT_FREQ, SYSTEM_TIME_HZ); switch ( c->mode ) @@ -118,7 +121,7 @@ static int pit_get_out(PITState *pit, int channel) ASSERT(spin_is_locked(&pit->lock)); - d = muldiv64(hvm_get_guest_time(v) - pit->count_load_time[channel], + d = muldiv64(get_guest_time(v) - pit->count_load_time[channel], PIT_FREQ, SYSTEM_TIME_HZ); switch ( s->mode ) @@ -165,7 +168,7 @@ static void pit_set_gate(PITState *pit, int channel, int val) case 3: /* Restart counting on rising edge. */ if ( s->gate < val ) - pit->count_load_time[channel] = hvm_get_guest_time(v); + pit->count_load_time[channel] = get_guest_time(v); break; } @@ -181,7 +184,7 @@ int pit_get_gate(PITState *pit, int channel) static void pit_time_fired(struct vcpu *v, void *priv) { uint64_t *count_load_time = priv; - *count_load_time = hvm_get_guest_time(v); + *count_load_time = get_guest_time(v); } static void pit_load_count(PITState *pit, int channel, int val) @@ -198,7 +201,7 @@ static void pit_load_count(PITState *pit, int channel, int val) if ( v == NULL ) pit->count_load_time[channel] = 0; else - pit->count_load_time[channel] = hvm_get_guest_time(v); + pit->count_load_time[channel] = get_guest_time(v); s->count = val; period = DIV_ROUND(val * SYSTEM_TIME_HZ, PIT_FREQ); @@ -436,7 +439,7 @@ static int pit_load(struct domain *d, hvm_domain_context_t *h) * time jitter here, but the wall-clock will have jumped massively, so * we hope the guest can handle it. */ - pit->pt0.last_plt_gtime = hvm_get_guest_time(d->vcpu[0]); + pit->pt0.last_plt_gtime = get_guest_time(d->vcpu[0]); for ( i = 0; i < 3; i++ ) pit_load_count(pit, i, pit->hw.channels[i].count); diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index cb62e5e083..1b4b4f5840 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -39,6 +39,9 @@ u64 hvm_get_guest_time(struct vcpu *v) struct pl_time *pl = &v->domain->arch.hvm_domain.pl_time; u64 now; + /* Called from device models shared with PV guests. Be careful. */ + ASSERT(is_hvm_vcpu(v)); + spin_lock(&pl->pl_time_lock); now = get_s_time() + pl->stime_offset; if ( (int64_t)(now - pl->last_guest_time) >= 0 ) |