diff options
author | Bharat Bhushan <r65777@freescale.com> | 2011-03-25 01:02:13 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-05-11 07:57:04 -0400 |
commit | 09000adb86550d2895b64faa52e64eaec3cae7b2 (patch) | |
tree | e2a932b4735b1296e2df760fea26030286f9daaa /arch/powerpc/kvm | |
parent | 7c5625227ff8c81953e953d8e25c3eba2ab0aeb3 (diff) |
KVM: PPC: Fix issue clearing exit timing counters
Following dump is observed on host when clearing the exit timing counters
[root@p1021mds kvm]# echo -n 'c' > vm1200_vcpu0_timing
INFO: task echo:1276 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
echo D 0ff5bf94 0 1276 1190 0x00000000
Call Trace:
[c2157e40] [c0007908] __switch_to+0x9c/0xc4
[c2157e50] [c040293c] schedule+0x1b4/0x3bc
[c2157e90] [c04032dc] __mutex_lock_slowpath+0x74/0xc0
[c2157ec0] [c00369e4] kvmppc_init_timing_stats+0x20/0xb8
[c2157ed0] [c0036b00] kvmppc_exit_timing_write+0x84/0x98
[c2157ef0] [c00b9f90] vfs_write+0xc0/0x16c
[c2157f10] [c00ba284] sys_write+0x4c/0x90
[c2157f40] [c000e320] ret_from_syscall+0x0/0x3c
The vcpu->mutex is used by kvm_ioctl_* (KVM_RUN etc) and same was
used when clearing the stats (in kvmppc_init_timing_stats()). What happens
is that when the guest is idle then it held the vcpu->mutx. While the
exiting timing process waits for guest to release the vcpu->mutex and
a hang state is reached.
Now using seprate lock for exit timing stats.
Signed-off-by: Bharat Bhushan <Bharat.Bhushan@freescale.com>
Acked-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kvm/timing.c | 10 |
2 files changed, 11 insertions, 3 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 99758460efde..ec3d2e75c0a8 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -284,6 +284,10 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) | |||
284 | tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); | 284 | tasklet_init(&vcpu->arch.tasklet, kvmppc_decrementer_func, (ulong)vcpu); |
285 | vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; | 285 | vcpu->arch.dec_timer.function = kvmppc_decrementer_wakeup; |
286 | 286 | ||
287 | #ifdef CONFIG_KVM_EXIT_TIMING | ||
288 | mutex_init(&vcpu->arch.exit_timing_lock); | ||
289 | #endif | ||
290 | |||
287 | return 0; | 291 | return 0; |
288 | } | 292 | } |
289 | 293 | ||
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c index a021f5827a33..18f40fd3e98f 100644 --- a/arch/powerpc/kvm/timing.c +++ b/arch/powerpc/kvm/timing.c | |||
@@ -34,8 +34,8 @@ void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) | |||
34 | { | 34 | { |
35 | int i; | 35 | int i; |
36 | 36 | ||
37 | /* pause guest execution to avoid concurrent updates */ | 37 | /* Take a lock to avoid concurrent updates */ |
38 | mutex_lock(&vcpu->mutex); | 38 | mutex_lock(&vcpu->arch.exit_timing_lock); |
39 | 39 | ||
40 | vcpu->arch.last_exit_type = 0xDEAD; | 40 | vcpu->arch.last_exit_type = 0xDEAD; |
41 | for (i = 0; i < __NUMBER_OF_KVM_EXIT_TYPES; i++) { | 41 | for (i = 0; i < __NUMBER_OF_KVM_EXIT_TYPES; i++) { |
@@ -49,7 +49,7 @@ void kvmppc_init_timing_stats(struct kvm_vcpu *vcpu) | |||
49 | vcpu->arch.timing_exit.tv64 = 0; | 49 | vcpu->arch.timing_exit.tv64 = 0; |
50 | vcpu->arch.timing_last_enter.tv64 = 0; | 50 | vcpu->arch.timing_last_enter.tv64 = 0; |
51 | 51 | ||
52 | mutex_unlock(&vcpu->mutex); | 52 | mutex_unlock(&vcpu->arch.exit_timing_lock); |
53 | } | 53 | } |
54 | 54 | ||
55 | static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type) | 55 | static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type) |
@@ -65,6 +65,8 @@ static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | mutex_lock(&vcpu->arch.exit_timing_lock); | ||
69 | |||
68 | vcpu->arch.timing_count_type[type]++; | 70 | vcpu->arch.timing_count_type[type]++; |
69 | 71 | ||
70 | /* sum */ | 72 | /* sum */ |
@@ -93,6 +95,8 @@ static void add_exit_timing(struct kvm_vcpu *vcpu, u64 duration, int type) | |||
93 | vcpu->arch.timing_min_duration[type] = duration; | 95 | vcpu->arch.timing_min_duration[type] = duration; |
94 | if (unlikely(duration > vcpu->arch.timing_max_duration[type])) | 96 | if (unlikely(duration > vcpu->arch.timing_max_duration[type])) |
95 | vcpu->arch.timing_max_duration[type] = duration; | 97 | vcpu->arch.timing_max_duration[type] = duration; |
98 | |||
99 | mutex_unlock(&vcpu->arch.exit_timing_lock); | ||
96 | } | 100 | } |
97 | 101 | ||
98 | void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu) | 102 | void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu) |