Re: Errors on MMIO read access on VM suspend / resume operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 01/13/2011 05:22 AM, Avi Kivity wrote:
On 01/11/2011 06:19 PM, Stefan Berger wrote:

What puzzles me is that the read operation may be run twice but others don't.


Reads have split execution: kvm emulates the mmio instruction, notices that it cannot satisfy the read request, exits to qemu, then restarts the instruction. If the last step is omitted due to savevm, then kvm will exit back to qemu again and your device will see the read duplicated.

That would then explain it on the read-side. MMIO writes seem to be ok.

If you have insights as why the above may be occurring, please let me know. A simple solution to work around this may be to introduce a register holding the index into the result packet where to read the next byte from (rather than advancing an internal pointer to the next byte), though this would deviate the driver from the standard interface the model currently implements.

Most undesirable, I'd like to fix the bug.
In the meantime I modified the tpm_tis driver making use of the fact that the packet can be re-read. I reread the packet when I recognize that the TIS is running out of bytes early (due to double-read). That makes it work. Debugging output of the driver shows the retrying, implying that the double-reads do occur. This work-around is just 'masking' the problem.

Can you sprinkle some printfs() arount kvm_run (in qemu-kvm.c) to verify this?

Here's what I did:

diff --git a/kvm-all.c b/kvm-all.c
index cae24bb..7ba222a 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -31,7 +31,7 @@
 /* KVM uses PAGE_SIZE in it's definition of COALESCED_MMIO_MAX */
 #define PAGE_SIZE TARGET_PAGE_SIZE

-//#define DEBUG_KVM
+#define DEBUG_KVM

 #ifdef DEBUG_KVM
 #define DPRINTF(fmt, ...) \
@@ -874,6 +874,9 @@ int kvm_cpu_exec(CPUState *env)
         kvm_arch_pre_run(env, run);
         cpu_single_env = NULL;
         qemu_mutex_unlock_iothread();
+#ifdef DEBUG_KVM
+        fprintf(stderr,"ioctl(KVM_RUN)\n");
+#endif
         ret = kvm_vcpu_ioctl(env, KVM_RUN, 0);
         qemu_mutex_lock_iothread();
         cpu_single_env = env;



Good pattern:

  ioctl(KVM_RUN)
  -> KVM_EXIT_MMIO
  ioctl(KVM_RUN)
  -> ENTR
  no further KVM_RUNs

or

   ioctl(KVM_RUN)
   -> something other than KVM_EXIT_MMIO
   no further KVM_RUNs

Bad pattern:

   ioctl(KVM_RUN)
   -> KVM_EXIT_MMIO
   no further KVM_RUNs

Here's what I see in the failure case:

ioctl(KVM_RUN)
handle_mmio
ioctl(KVM_RUN)
handle_mmio
ioctl(KVM_RUN)
handle_mmio
ioctl(KVM_RUN)
handle_mmio
interrupt exit requested
0+0 records in
0+0 records out
0 bytes (0 B) copied, 9.18e-06 s, 0.0 kB/s
tpm_tis: suspend: locty 0 : r_offset = 61, w_offset = 0
tpm_tis: active locality     : 0
tpm_tis: state of locality 0 : 0x2
tpm_tis: register dump:
tpm_tis: 0x0000 : 000000a0
tpm_tis: 0x0008 : 0x8000008d
tpm_tis: 0x000c : 0x00000003
tpm_tis: 0x0010 : 0x00000000
tpm_tis: 0x0014 : 0x00000095
tpm_tis: 0x0018 : 0x00011290
tpm_tis: 0x0f00 : 0x00010001
tpm_tis: 0x0f04 : 0x00000001
tpm_tis: read offset   : 61
tpm_tis: result buffer :  00 c5 00 00 01 4f 00 00 00 00 00 00 00 01 00 03
tpm_tis:                  00 01 00 00 00 0c 00 00 08 00 00 00 00 02 00 00
tpm_tis:                  00 00 00 00 01 00 ca 47 12 16 3b e9 14 25 f7 f4
tpm_tis:                  b1 5e 69 c7 da 2d 5e f8 a3 82 04 bc e6>17 9e c5
tpm_tis:                  fd 2a f0 c0 01 13 c9 f2 c7 fb 5d e6 63 a7 db 48
tpm_tis:                  f2 85 bb 93 f1 b3 40 00 5b 27 70 5d 8c 28 79 89
tpm_tis:                  36 49 7d 2f 56 b8 28 d5 61 74 4d ff 1c cf 4b a9
tpm_tis:                  a1 a8 b1 9e 6f 89 02 a3 21 02 86 8b ab 73 14 9b
tpm_tis:                  79 6e 86 27 da a8 2d 2c 0f 9c 28 ae 8d b7 b8 66
tpm_tis:                  6a 20 92 3d 48 d0 c9 42 84 f6 2a ad e2 bd d3 11
tpm_tis:                  2b e9 90 8e 1f 64 e4 de 9d 12 75 4a db 3f de d7
tpm_tis:                  70 06 b0 95 47 56 9f a7 32 b6 20 1a 12 ea 8a ed
tpm_tis:                  24 b1 17 6b ad 4a 64 4b 64 b7 2c 1f 44 02 fe 2c
tpm_tis:                  d8 72 1b bb 9c 42 8c 64 46 f4 29 ad 9c ff ea 37
tpm_tis:                  48 77 26 4c 75 53 52 5a cb 6a 58 d5 d6 81 17 17
tpm_tis:                  27 97 44 bf d7 0d 46 3c 9f b3 70 3f 5c 5c b1 ba
tpm_tis:                  86 5e 9c 78 bc 4c 40 41 90 ed 79 b2 06 64 73 6e
tpm_tis:                  64 18 e7 d0 9f 4d 7d d6 bb 2d 39 18 e1 41 3f 34
tpm_tis:                  2b 9e a4 8e 70 a1 fa 35 1d f3 cf be 5a 73 4d dd
tpm_tis:                  49 dd 57 79 5b be 48 c6 44 3c 00 01 68 07 b3 2d
tpm_tis:                  42 08 2e 51 93 1a cf db 34 de 10 1d 94 fe 9a
tpm_tis: write offset  : 0
tpm_tis: request buffer:>00 c2 00 00 00 3b 00 00 00 81 40 00 00 06 78 e8
tpm_tis:                  a5 47 c3 e9 67 27 ac 27 5a a7 9c 53 19 f9 f0 cd
tpm_tis:                  8b 93 4a 82 85 af 00 e9 b8 c6 80 92 42 fb c6 55
tpm_tis:                  06 00 f2 62 52 7b 8b cd 64 65 95
48+11535 records in
48+11535 records out
500881189 bytes (501 MB) copied, 14.282 s, 35.1 MB/s
2011-01-14 13:55:57.871: shutting down

Immediately following is the restore part:

2011-01-14 13:55:59.575: starting up
LC_ALL=C PATH=/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin HOME=/root USER=root LOGNAME=root QEMU_AUDIO_DRV=none [...]
kvm_init_vcpu
tpm_tis: resume : locty 0 : r_offset = 61, w_offset = 0
kvm_cpu_exec()
interrupt exit requested
kvm_cpu_exec()
ioctl(KVM_RUN)
irq_window_open
kvm_cpu_exec()
ioctl(KVM_RUN)
handle_mmio
ioctl(KVM_RUN)
handle_mmio


Cheers!
   Stefan

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux