From 1138f24645e9e1e2d55d280caab4e2539dfcdb49 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Oct 2015 10:02:52 +0200 Subject: [PATCH 01/12] qemu-gdb: allow using glibc_pointer_guard() on core dumps get_fs_base() cannot be run on a core dump, because it uses the arch_prctl system call. The fs base is the value that is returned by pthread_self(), and it would be nice to just glean it from the "info threads" output: * 1 Thread 0x7f16a3fff700 (LWP 33642) pthread_cond_wait@@GLIBC_2.3.2 () ^^^^^^^^^^^^^^ but unfortunately the gdb API does not provide that. Instead, we can look for the "arg" argument of the start_thread function if glibc debug information are available. If not, fall back to the old mechanism. Signed-off-by: Paolo Bonzini Message-id: 1444636974-19950-2-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- scripts/qemugdb/coroutine.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py index 3c54918b5d..b1d4546fe6 100644 --- a/scripts/qemugdb/coroutine.py +++ b/scripts/qemugdb/coroutine.py @@ -16,7 +16,8 @@ import gdb def get_fs_base(): - '''Fetch %fs base value using arch_prctl(ARCH_GET_FS)''' + '''Fetch %fs base value using arch_prctl(ARCH_GET_FS). This is + pthread_self().''' # %rsp - 120 is scratch space according to the SystemV ABI old = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)') gdb.execute('call arch_prctl(0x1003, $rsp - 120)', False, True) @@ -24,9 +25,22 @@ def get_fs_base(): gdb.execute('set *(uint64_t*)($rsp - 120) = %s' % old, False, True) return fs_base +def pthread_self(): + '''Fetch pthread_self() from the glibc start_thread function.''' + f = gdb.newest_frame() + while f.name() != 'start_thread': + f = f.older() + if f is None: + return get_fs_base() + + try: + return f.read_var("arg") + except ValueError: + return get_fs_base() + def get_glibc_pointer_guard(): '''Fetch glibc pointer guard value''' - fs_base = get_fs_base() + fs_base = pthread_self() return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base) def glibc_ptr_demangle(val, pointer_guard): From 80ab31b257ba3aaa98ce6f1e36592aa20c5366c1 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Oct 2015 10:02:53 +0200 Subject: [PATCH 02/12] qemu-gdb: extract parts of "qemu coroutine" implementation Provide useful Python functions to reach and decipher a jmpbuf. Signed-off-by: Paolo Bonzini Message-id: 1444636974-19950-3-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- scripts/qemugdb/coroutine.py | 56 +++++++++++++++++------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py index b1d4546fe6..b5c86787c4 100644 --- a/scripts/qemugdb/coroutine.py +++ b/scripts/qemugdb/coroutine.py @@ -47,8 +47,7 @@ def glibc_ptr_demangle(val, pointer_guard): '''Undo effect of glibc's PTR_MANGLE()''' return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard)) -def bt_jmpbuf(jmpbuf): - '''Backtrace a jmpbuf''' +def get_jmpbuf_regs(jmpbuf): JB_RBX = 0 JB_RBP = 1 JB_R12 = 2 @@ -58,35 +57,35 @@ def bt_jmpbuf(jmpbuf): JB_RSP = 6 JB_PC = 7 - old_rbx = gdb.parse_and_eval('(uint64_t)$rbx') - old_rbp = gdb.parse_and_eval('(uint64_t)$rbp') - old_rsp = gdb.parse_and_eval('(uint64_t)$rsp') - old_r12 = gdb.parse_and_eval('(uint64_t)$r12') - old_r13 = gdb.parse_and_eval('(uint64_t)$r13') - old_r14 = gdb.parse_and_eval('(uint64_t)$r14') - old_r15 = gdb.parse_and_eval('(uint64_t)$r15') - old_rip = gdb.parse_and_eval('(uint64_t)$rip') - pointer_guard = get_glibc_pointer_guard() - gdb.execute('set $rbx = %s' % jmpbuf[JB_RBX]) - gdb.execute('set $rbp = %s' % glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard)) - gdb.execute('set $rsp = %s' % glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard)) - gdb.execute('set $r12 = %s' % jmpbuf[JB_R12]) - gdb.execute('set $r13 = %s' % jmpbuf[JB_R13]) - gdb.execute('set $r14 = %s' % jmpbuf[JB_R14]) - gdb.execute('set $r15 = %s' % jmpbuf[JB_R15]) - gdb.execute('set $rip = %s' % glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard)) + return {'rbx': jmpbuf[JB_RBX], + 'rbp': glibc_ptr_demangle(jmpbuf[JB_RBP], pointer_guard), + 'rsp': glibc_ptr_demangle(jmpbuf[JB_RSP], pointer_guard), + 'r12': jmpbuf[JB_R12], + 'r13': jmpbuf[JB_R13], + 'r14': jmpbuf[JB_R14], + 'r15': jmpbuf[JB_R15], + 'rip': glibc_ptr_demangle(jmpbuf[JB_PC], pointer_guard) } + +def bt_jmpbuf(jmpbuf): + '''Backtrace a jmpbuf''' + regs = get_jmpbuf_regs(jmpbuf) + old = dict() + + for i in regs: + old[i] = gdb.parse_and_eval('(uint64_t)$%s' % i) + + for i in regs: + gdb.execute('set $%s = %s' % (i, regs[i])) gdb.execute('bt') - gdb.execute('set $rbx = %s' % old_rbx) - gdb.execute('set $rbp = %s' % old_rbp) - gdb.execute('set $rsp = %s' % old_rsp) - gdb.execute('set $r12 = %s' % old_r12) - gdb.execute('set $r13 = %s' % old_r13) - gdb.execute('set $r14 = %s' % old_r14) - gdb.execute('set $r15 = %s' % old_r15) - gdb.execute('set $rip = %s' % old_rip) + for i in regs: + gdb.execute('set $%s = %s' % (i, old[i])) + +def coroutine_to_jmpbuf(co): + coroutine_pointer = co.cast(gdb.lookup_type('CoroutineUContext').pointer()) + return coroutine_pointer['env']['__jmpbuf'] class CoroutineCommand(gdb.Command): @@ -101,5 +100,4 @@ def invoke(self, arg, from_tty): gdb.write('usage: qemu coroutine \n') return - coroutine_pointer = gdb.parse_and_eval(argv[0]).cast(gdb.lookup_type('CoroutineUContext').pointer()) - bt_jmpbuf(coroutine_pointer['env']['__jmpbuf']) + bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0]))) From a201b0ff28d9fa0f965450c1ba7191eca69f9fd5 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Mon, 12 Oct 2015 10:02:54 +0200 Subject: [PATCH 03/12] qemu-gdb: add $qemu_coroutine_sp and $qemu_coroutine_pc These can be useful to manually get a stack trace of a coroutine inside a core dump. Signed-off-by: Paolo Bonzini Message-id: 1444636974-19950-4-git-send-email-pbonzini@redhat.com Signed-off-by: Stefan Hajnoczi --- scripts/qemu-gdb.py | 3 +++ scripts/qemugdb/coroutine.py | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py index d6f2e5a903..ef2fd191df 100644 --- a/scripts/qemu-gdb.py +++ b/scripts/qemu-gdb.py @@ -38,6 +38,9 @@ def __init__(self): coroutine.CoroutineCommand() mtree.MtreeCommand() +coroutine.CoroutineSPFunction() +coroutine.CoroutinePCFunction() + # Default to silently passing through SIGUSR1, because QEMU sends it # to itself a lot. gdb.execute('handle SIGUSR1 pass noprint nostop') diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py index b5c86787c4..ab699794ab 100644 --- a/scripts/qemugdb/coroutine.py +++ b/scripts/qemugdb/coroutine.py @@ -15,6 +15,8 @@ import gdb +VOID_PTR = gdb.lookup_type('void').pointer() + def get_fs_base(): '''Fetch %fs base value using arch_prctl(ARCH_GET_FS). This is pthread_self().''' @@ -101,3 +103,17 @@ def invoke(self, arg, from_tty): return bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0]))) + +class CoroutineSPFunction(gdb.Function): + def __init__(self): + gdb.Function.__init__(self, 'qemu_coroutine_sp') + + def invoke(self, addr): + return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rsp'].cast(VOID_PTR) + +class CoroutinePCFunction(gdb.Function): + def __init__(self): + gdb.Function.__init__(self, 'qemu_coroutine_pc') + + def invoke(self, addr): + return get_jmpbuf_regs(coroutine_to_jmpbuf(addr))['rip'].cast(VOID_PTR) From 54d8ec84fa444ed7c05e03f96895ba69a2b2e5bc Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 16 Oct 2015 12:25:52 +0200 Subject: [PATCH 04/12] s390x: include HW_COMPAT_* props We want to inherit generic hw compat as well. Signed-off-by: Cornelia Huck Acked-by: Christian Borntraeger Message-id: 1444991154-79217-2-git-send-email-cornelia.huck@de.ibm.com Signed-off-by: Stefan Hajnoczi --- hw/s390x/s390-virtio-ccw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index faba773592..84221f4f57 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -20,6 +20,7 @@ #include "qemu/config-file.h" #include "s390-pci-bus.h" #include "hw/s390x/storage-keys.h" +#include "hw/compat.h" #define TYPE_S390_CCW_MACHINE "s390-ccw-machine" @@ -236,6 +237,7 @@ static const TypeInfo ccw_machine_info = { }; #define CCW_COMPAT_2_4 \ + HW_COMPAT_2_4 \ {\ .driver = TYPE_S390_SKEYS,\ .property = "migration-enabled",\ From 80fd50f96b8dc46e185f61d9b6438a6414507076 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 16 Oct 2015 12:25:53 +0200 Subject: [PATCH 05/12] ppc/spapr: add 2.4 compat props HW_COMPAT_2_4 will become non-empty: prepare for it. Signed-off-by: Cornelia Huck Message-id: 1444991154-79217-3-git-send-email-cornelia.huck@de.ibm.com Signed-off-by: Stefan Hajnoczi --- hw/ppc/spapr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 288b57e24f..0ed8527969 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -2285,7 +2285,11 @@ static const TypeInfo spapr_machine_info = { }, }; +#define SPAPR_COMPAT_2_4 \ + HW_COMPAT_2_4 + #define SPAPR_COMPAT_2_3 \ + SPAPR_COMPAT_2_4 \ HW_COMPAT_2_3 \ {\ .driver = "spapr-pci-host-bridge",\ @@ -2399,11 +2403,16 @@ static const TypeInfo spapr_machine_2_3_info = { static void spapr_machine_2_4_class_init(ObjectClass *oc, void *data) { + static GlobalProperty compat_props[] = { + SPAPR_COMPAT_2_4 + { /* end of list */ } + }; MachineClass *mc = MACHINE_CLASS(oc); mc->desc = "pSeries Logical Partition (PAPR compliant) v2.4"; mc->alias = "pseries"; mc->is_default = 0; + mc->compat_props = compat_props; } static const TypeInfo spapr_machine_2_4_info = { From ed65fd1a2750d24290354cc7ea49caec7c13e30b Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Fri, 16 Oct 2015 12:25:54 +0200 Subject: [PATCH 06/12] virtio-blk: switch off scsi-passthrough by default Devices that are compliant with virtio-1 do not support scsi passthrough any more (and it has not been a recommended setup anyway for quite some time). To avoid having to switch it off explicitly in newer qemus that turn on virtio-1 by default, let's switch the default to scsi=false for 2.5. Signed-off-by: Cornelia Huck Message-id: 1444991154-79217-4-git-send-email-cornelia.huck@de.ibm.com Signed-off-by: Stefan Hajnoczi --- hw/block/virtio-blk.c | 2 +- include/hw/compat.h | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 3e230debb8..45a24e4fa6 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -972,7 +972,7 @@ static Property virtio_blk_properties[] = { DEFINE_PROP_STRING("serial", VirtIOBlock, conf.serial), DEFINE_PROP_BIT("config-wce", VirtIOBlock, conf.config_wce, 0, true), #ifdef __linux__ - DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, true), + DEFINE_PROP_BIT("scsi", VirtIOBlock, conf.scsi, 0, false), #endif DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0, true), diff --git a/include/hw/compat.h b/include/hw/compat.h index 095de5d12f..93e71afb4a 100644 --- a/include/hw/compat.h +++ b/include/hw/compat.h @@ -2,7 +2,11 @@ #define HW_COMPAT_H #define HW_COMPAT_2_4 \ - /* empty */ + {\ + .driver = "virtio-blk-device",\ + .property = "scsi",\ + .value = "true",\ + }, #define HW_COMPAT_2_3 \ {\ From c900ef86c5e30e1adec0f79350edc3f30ebee285 Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" Date: Tue, 27 Oct 2015 13:09:45 +0000 Subject: [PATCH 07/12] gdb command: qemu handlers A new gdb commands are added: qemu handlers That dumps an AioContext list (by default qemu_aio_context) possibly including a backtrace for cases it knows about (with the verbose option). Intended to help find why something is hanging waiting for IO. Use 'qemu handlers --verbose iohandler_ctx' to find out why your incoming migration is stuck. Signed-off-by: Dr. David Alan Gilbert Message-id: 1445951385-11924-1-git-send-email-dgilbert@redhat.com V2: Merge into one command with optional handlers arg, and only do backtrace in verbose mode (gdb) qemu handlers ---- {pfd = {fd = 6, events = 25, revents = 0}, io_read = 0x55869656ffd0 , io_write = 0x0, deleted = 0, opaque = 0x558698c4ce08, node = {le_next = 0x0, le_prev = 0x558698c4cdc0}} (gdb) qemu handlers iohandler_ctx ---- {pfd = {fd = 9, events = 25, revents = 0}, io_read = 0x558696581380 , io_write = 0x0, deleted = 0, opaque = 0x558698dc99d0, node = {le_next = 0x558698c4cca0, le_prev = 0x558698c4c1d0}} ---- {pfd = {fd = 4, events = 25, revents = 0}, io_read = 0x55869657b330 , io_write = 0x0, deleted = 0, opaque = 0x4, node = {le_next = 0x558698c4c260, le_prev = 0x558699f72508}} ---- {pfd = {fd = 5, events = 25, revents = 0}, io_read = 0x55869656ffd0 , io_write = 0x0, deleted = 0, opaque = 0x558698c4c218, node = {le_next = 0x0, le_prev = 0x558698c4ccc8}} ---- (gdb) qemu handlers --verbose iohandler_ctx ---- {pfd = {fd = 9, events = 25, revents = 0}, io_read = 0x558696581380 , io_write = 0x0, deleted = 0, opaque = 0x558698dc99d0, node = {le_next = 0x558698c4cca0, le_prev = 0x558698c4c1d0}} #0 0x0000558696581820 in qemu_coroutine_switch (from_=from_@entry=0x558698cb3cf0, to_=to_@entry=0x7f421c37eac8, action=action@entry=COROUTINE_YIELD) at /home/dgilbert/git/qemu/coroutine-ucontext.c:177 #1 0x0000558696580c00 in qemu_coroutine_yield () at /home/dgilbert/git/qemu/qemu-coroutine.c:145 #2 0x00005586965814f5 in yield_until_fd_readable (fd=9) at /home/dgilbert/git/qemu/qemu-coroutine-io.c:90 #3 0x0000558696523937 in socket_get_buffer (opaque=0x55869a3dc620, buf=0x558698c505a0 "", pos=, size=32768) at /home/dgilbert/git/qemu/migration/qemu-file-unix.c:101 #4 0x0000558696521fac in qemu_fill_buffer (f=0x558698c50570) at /home/dgilbert/git/qemu/migration/qemu-file.c:227 #5 0x0000558696522989 in qemu_peek_byte (f=0x558698c50570, offset=0) at /home/dgilbert/git/qemu/migration/qemu-file.c:507 #6 0x0000558696522bf4 in qemu_get_be32 (f=0x558698c50570) at /home/dgilbert/git/qemu/migration/qemu-file.c:520 #7 0x0000558696522bf4 in qemu_get_be32 (f=f@entry=0x558698c50570) at /home/dgilbert/git/qemu/migration/qemu-file.c:604 #8 0x0000558696347e5c in qemu_loadvm_state (f=f@entry=0x558698c50570) at /home/dgilbert/git/qemu/migration/savevm.c:1821 #9 0x000055869651de8c in process_incoming_migration_co (opaque=0x558698c50570) at /home/dgilbert/git/qemu/migration/migration.c:336 #10 0x000055869658188a in coroutine_trampoline (i0=, i1=) at /home/dgilbert/git/qemu/coroutine-ucontext.c:80 #11 0x00007f420f05df10 in __start_context () at /lib64/libc.so.6 #12 0x00007ffc40815f50 in () #13 0x0000000000000000 in () ---- Signed-off-by: Stefan Hajnoczi --- scripts/qemu-gdb.py | 3 ++- scripts/qemugdb/aio.py | 58 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 scripts/qemugdb/aio.py diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py index ef2fd191df..b3f8e04f77 100644 --- a/scripts/qemu-gdb.py +++ b/scripts/qemu-gdb.py @@ -26,7 +26,7 @@ sys.path.append(os.path.dirname(__file__)) -from qemugdb import mtree, coroutine +from qemugdb import aio, mtree, coroutine class QemuCommand(gdb.Command): '''Prefix for QEMU debug support commands''' @@ -37,6 +37,7 @@ def __init__(self): QemuCommand() coroutine.CoroutineCommand() mtree.MtreeCommand() +aio.HandlersCommand() coroutine.CoroutineSPFunction() coroutine.CoroutinePCFunction() diff --git a/scripts/qemugdb/aio.py b/scripts/qemugdb/aio.py new file mode 100644 index 0000000000..2ba00c4444 --- /dev/null +++ b/scripts/qemugdb/aio.py @@ -0,0 +1,58 @@ +#!/usr/bin/python + +# GDB debugging support: aio/iohandler debug +# +# Copyright (c) 2015 Red Hat, Inc. +# +# Author: Dr. David Alan Gilbert +# +# This work is licensed under the terms of the GNU GPL, version 2 or +# later. See the COPYING file in the top-level directory. +# + +import gdb +from qemugdb import coroutine + +def isnull(ptr): + return ptr == gdb.Value(0).cast(ptr.type) + +def dump_aiocontext(context, verbose): + '''Display a dump and backtrace for an aiocontext''' + cur = context['aio_handlers']['lh_first'] + # Get pointers to functions we're going to process specially + sym_fd_coroutine_enter = gdb.parse_and_eval('fd_coroutine_enter') + + while not isnull(cur): + entry = cur.dereference() + gdb.write('----\n%s\n' % entry) + if verbose and cur['io_read'] == sym_fd_coroutine_enter: + coptr = (cur['opaque'].cast(gdb.lookup_type('FDYieldUntilData').pointer()))['co'] + coptr = coptr.cast(gdb.lookup_type('CoroutineUContext').pointer()) + coroutine.bt_jmpbuf(coptr['env']['__jmpbuf']) + cur = cur['node']['le_next']; + + gdb.write('----\n') + +class HandlersCommand(gdb.Command): + '''Display aio handlers''' + def __init__(self): + gdb.Command.__init__(self, 'qemu handlers', gdb.COMMAND_DATA, + gdb.COMPLETE_NONE) + + def invoke(self, arg, from_tty): + verbose = False + argv = gdb.string_to_argv(arg) + + if len(argv) > 0 and argv[0] == '--verbose': + verbose = True + argv.pop(0) + + if len(argv) > 1: + gdb.write('usage: qemu handlers [--verbose] [handler]\n') + return + + if len(argv) == 1: + handlers_name = argv[0] + else: + handlers_name = 'qemu_aio_context' + dump_aiocontext(gdb.parse_and_eval(handlers_name), verbose) From 10a06fd65f667a972848ebbbcac11bdba931b544 Mon Sep 17 00:00:00 2001 From: Pavel Butsykin Date: Mon, 26 Oct 2015 14:42:57 +0300 Subject: [PATCH 08/12] virtio: sync the dataplane vring state to the virtqueue before virtio_save When creating snapshot with the dataplane enabled, the snapshot file gets not the actual state of virtqueue, because the current state is stored in VirtIOBlockDataPlane. Therefore, before saving snapshot need to sync the dataplane vring state to the virtqueue. The dataplane will resume its work at the next notify virtqueue. When snapshot loads with loadvm we get a message: VQ 0 size 0x80 Guest index 0x15f5 inconsistent with Host index 0x0: delta 0x15f5 error while loading state for instance 0x0 of device '0000:00:08.0/virtio-blk' Error -1 while loading VM state to reproduce the error I used the following hmp commands: savevm snap1 loadvm snap1 qemu parameters: --enable-kvm -smp 4 -m 1024 -drive file=/var/lib/libvirt/images/centos6.4.qcow2,if=none,id=drive-virtio-disk0,format=qcow2,cache=none,aio=native -device virtio-blk-pci,scsi=off,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,id=virtio-disk0 -set device.virtio-disk0.x-data-plane=on Signed-off-by: Pavel Butsykin Signed-off-by: Denis V. Lunev Message-id: 1445859777-2982-1-git-send-email-den@openvz.org CC: Stefan Hajnoczi CC: "Michael S. Tsirkin" CC: Kevin Wolf CC: Paolo Bonzini Signed-off-by: Stefan Hajnoczi --- hw/block/virtio-blk.c | 5 +++++ hw/scsi/virtio-scsi.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c index 45a24e4fa6..093e475dc9 100644 --- a/hw/block/virtio-blk.c +++ b/hw/block/virtio-blk.c @@ -798,6 +798,11 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status) static void virtio_blk_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOBlock *s = VIRTIO_BLK(vdev); + + if (s->dataplane) { + virtio_blk_data_plane_stop(s->dataplane); + } virtio_save(vdev, f); } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 46553e1e68..76554011cb 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -653,6 +653,11 @@ static void virtio_scsi_reset(VirtIODevice *vdev) static void virtio_scsi_save(QEMUFile *f, void *opaque) { VirtIODevice *vdev = VIRTIO_DEVICE(opaque); + VirtIOSCSI *s = VIRTIO_SCSI(vdev); + + if (s->dataplane_started) { + virtio_scsi_dataplane_stop(s); + } virtio_save(vdev, f); } From e3382ef0ea2724f5f09271a608e8f68ede5d844d Mon Sep 17 00:00:00 2001 From: Sai Pavan Boddu Date: Thu, 8 Oct 2015 18:51:01 +0530 Subject: [PATCH 09/12] sd.h: Move sd.h to include/hw/sd/ Create a sd directory under include/hw/ and move sd.h to include/hw/sd/ Signed-off-by: Sai Pavan Boddu Reviewed-by: Alistair Francis Reviewed-by: Peter Crosthwaite Signed-off-by: Stefan Hajnoczi --- hw/sd/milkymist-memcard.c | 2 +- hw/sd/omap_mmc.c | 2 +- hw/sd/pl181.c | 2 +- hw/sd/pxa2xx_mmci.c | 2 +- hw/sd/sd.c | 2 +- hw/sd/sdhci.h | 2 +- hw/sd/ssi-sd.c | 2 +- include/hw/{ => sd}/sd.h | 0 8 files changed, 7 insertions(+), 7 deletions(-) rename include/hw/{ => sd}/sd.h (100%) diff --git a/hw/sd/milkymist-memcard.c b/hw/sd/milkymist-memcard.c index 2209ef1d52..b430d56687 100644 --- a/hw/sd/milkymist-memcard.c +++ b/hw/sd/milkymist-memcard.c @@ -28,7 +28,7 @@ #include "qemu/error-report.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" enum { ENABLE_CMD_TX = (1<<0), diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c index 35d8033402..5bc47193f9 100644 --- a/hw/sd/omap_mmc.c +++ b/hw/sd/omap_mmc.c @@ -18,7 +18,7 @@ */ #include "hw/hw.h" #include "hw/arm/omap.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" struct omap_mmc_s { qemu_irq irq; diff --git a/hw/sd/pl181.c b/hw/sd/pl181.c index 5242176a33..326c53ad92 100644 --- a/hw/sd/pl181.c +++ b/hw/sd/pl181.c @@ -10,7 +10,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/sysbus.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" //#define DEBUG_PL181 1 diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c index d1fe6d58e8..b217080075 100644 --- a/hw/sd/pxa2xx_mmci.c +++ b/hw/sd/pxa2xx_mmci.c @@ -12,7 +12,7 @@ #include "hw/hw.h" #include "hw/arm/pxa.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" #include "hw/qdev.h" struct PXA2xxMMCIState { diff --git a/hw/sd/sd.c b/hw/sd/sd.c index 393a75c0bc..ce4d44be91 100644 --- a/hw/sd/sd.c +++ b/hw/sd/sd.c @@ -31,7 +31,7 @@ #include "hw/hw.h" #include "sysemu/block-backend.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" #include "qemu/bitmap.h" //#define DEBUG_SD 1 diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci.h index e2de92d553..4461d0a205 100644 --- a/hw/sd/sdhci.h +++ b/hw/sd/sdhci.h @@ -29,7 +29,7 @@ #include "hw/block/block.h" #include "hw/pci/pci.h" #include "hw/sysbus.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" /* R/W SDMA System Address register 0x0 */ #define SDHC_SYSAD 0x00 diff --git a/hw/sd/ssi-sd.c b/hw/sd/ssi-sd.c index e4b2d4f83b..c49ff62f56 100644 --- a/hw/sd/ssi-sd.c +++ b/hw/sd/ssi-sd.c @@ -13,7 +13,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "hw/ssi.h" -#include "hw/sd.h" +#include "hw/sd/sd.h" //#define DEBUG_SSI_SD 1 diff --git a/include/hw/sd.h b/include/hw/sd/sd.h similarity index 100% rename from include/hw/sd.h rename to include/hw/sd/sd.h From 637d23beb607765033067c5cb08e0d66afaf8f4c Mon Sep 17 00:00:00 2001 From: Sai Pavan Boddu Date: Thu, 8 Oct 2015 18:51:02 +0530 Subject: [PATCH 10/12] sdhci: Split sdhci.h for public and internal device usage Split sdhci.h into pubilc version (i.e include/hw/sd/sdhci.h) and internal version (i.e hw/sd/sdhci-interna.h) based on register declarations and object declaration. Signed-off-by: Sai Pavan Boddu Reviewed-by: Alistair Francis Reviewed-by: Peter Crosthwaite Signed-off-by: Stefan Hajnoczi --- hw/sd/{sdhci.h => sdhci-internal.h} | 73 ++-------------------- hw/sd/sdhci.c | 3 +- include/hw/sd/sdhci.h | 94 +++++++++++++++++++++++++++++ 3 files changed, 99 insertions(+), 71 deletions(-) rename hw/sd/{sdhci.h => sdhci-internal.h} (75%) create mode 100644 include/hw/sd/sdhci.h diff --git a/hw/sd/sdhci.h b/hw/sd/sdhci-internal.h similarity index 75% rename from hw/sd/sdhci.h rename to hw/sd/sdhci-internal.h index 4461d0a205..c712daf4ee 100644 --- a/hw/sd/sdhci.h +++ b/hw/sd/sdhci-internal.h @@ -21,15 +21,10 @@ * You should have received a copy of the GNU General Public License along * with this program; if not, see . */ +#ifndef SDHCI_INTERNAL_H +#define SDHCI_INTERNAL_H -#ifndef SDHCI_H -#define SDHCI_H - -#include "qemu-common.h" -#include "hw/block/block.h" -#include "hw/pci/pci.h" -#include "hw/sysbus.h" -#include "hw/sd/sd.h" +#include "hw/sd/sdhci.h" /* R/W SDMA System Address register 0x0 */ #define SDHC_SYSAD 0x00 @@ -232,66 +227,6 @@ enum { sdhc_gap_write = 2 /* SDHC stopped at block gap during write operation */ }; -/* SD/MMC host controller state */ -typedef struct SDHCIState { - union { - PCIDevice pcidev; - SysBusDevice busdev; - }; - SDState *card; - MemoryRegion iomem; - BlockConf conf; - - QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ - QEMUTimer *transfer_timer; - qemu_irq eject_cb; - qemu_irq ro_cb; - qemu_irq irq; - - uint32_t sdmasysad; /* SDMA System Address register */ - uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ - uint16_t blkcnt; /* Blocks count for current transfer */ - uint32_t argument; /* Command Argument Register */ - uint16_t trnmod; /* Transfer Mode Setting Register */ - uint16_t cmdreg; /* Command Register */ - uint32_t rspreg[4]; /* Response Registers 0-3 */ - uint32_t prnsts; /* Present State Register */ - uint8_t hostctl; /* Host Control Register */ - uint8_t pwrcon; /* Power control Register */ - uint8_t blkgap; /* Block Gap Control Register */ - uint8_t wakcon; /* WakeUp Control Register */ - uint16_t clkcon; /* Clock control Register */ - uint8_t timeoutcon; /* Timeout Control Register */ - uint8_t admaerr; /* ADMA Error Status Register */ - uint16_t norintsts; /* Normal Interrupt Status Register */ - uint16_t errintsts; /* Error Interrupt Status Register */ - uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ - uint16_t errintstsen; /* Error Interrupt Status Enable Register */ - uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ - uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ - uint16_t acmd12errsts; /* Auto CMD12 error status register */ - uint64_t admasysaddr; /* ADMA System Address Register */ - - uint32_t capareg; /* Capabilities Register */ - uint32_t maxcurr; /* Maximum Current Capabilities Register */ - uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ - uint32_t buf_maxsz; - uint16_t data_count; /* current element in FIFO buffer */ - uint8_t stopped_state;/* Current SDHC state */ - /* Buffer Data Port Register - virtual access point to R and W buffers */ - /* Software Reset Register - always reads as 0 */ - /* Force Event Auto CMD12 Error Interrupt Reg - write only */ - /* Force Event Error Interrupt Register- write only */ - /* RO Host Controller Version Register always reads as 0x2401 */ -} SDHCIState; - extern const VMStateDescription sdhci_vmstate; -#define TYPE_PCI_SDHCI "sdhci-pci" -#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) - -#define TYPE_SYSBUS_SDHCI "generic-sdhci" -#define SYSBUS_SDHCI(obj) \ - OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) - -#endif /* SDHCI_H */ +#endif diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c index 7f73527d44..d70d1a6ab9 100644 --- a/hw/sd/sdhci.c +++ b/hw/sd/sdhci.c @@ -29,8 +29,7 @@ #include "sysemu/dma.h" #include "qemu/timer.h" #include "qemu/bitops.h" - -#include "sdhci.h" +#include "sdhci-internal.h" /* host controller debug messages */ #ifndef SDHC_DEBUG diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h new file mode 100644 index 0000000000..9b3031fb81 --- /dev/null +++ b/include/hw/sd/sdhci.h @@ -0,0 +1,94 @@ +/* + * SD Association Host Standard Specification v2.0 controller emulation + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. + * Mitsyanko Igor + * Peter A.G. Crosthwaite + * + * Based on MMC controller for Samsung S5PC1xx-based board emulation + * by Alexey Merkulov and Vladimir Monakhov. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * + * You should have received a copy of the GNU _General Public License along + * with this program; if not, see . + */ + +#ifndef SDHCI_H +#define SDHCI_H + +#include "qemu-common.h" +#include "hw/block/block.h" +#include "hw/pci/pci.h" +#include "hw/sysbus.h" +#include "hw/sd/sd.h" + +/* SD/MMC host controller state */ +typedef struct SDHCIState { + union { + PCIDevice pcidev; + SysBusDevice busdev; + }; + SDState *card; + MemoryRegion iomem; + BlockConf conf; + + QEMUTimer *insert_timer; /* timer for 'changing' sd card. */ + QEMUTimer *transfer_timer; + qemu_irq eject_cb; + qemu_irq ro_cb; + qemu_irq irq; + + uint32_t sdmasysad; /* SDMA System Address register */ + uint16_t blksize; /* Host DMA Buff Boundary and Transfer BlkSize Reg */ + uint16_t blkcnt; /* Blocks count for current transfer */ + uint32_t argument; /* Command Argument Register */ + uint16_t trnmod; /* Transfer Mode Setting Register */ + uint16_t cmdreg; /* Command Register */ + uint32_t rspreg[4]; /* Response Registers 0-3 */ + uint32_t prnsts; /* Present State Register */ + uint8_t hostctl; /* Host Control Register */ + uint8_t pwrcon; /* Power control Register */ + uint8_t blkgap; /* Block Gap Control Register */ + uint8_t wakcon; /* WakeUp Control Register */ + uint16_t clkcon; /* Clock control Register */ + uint8_t timeoutcon; /* Timeout Control Register */ + uint8_t admaerr; /* ADMA Error Status Register */ + uint16_t norintsts; /* Normal Interrupt Status Register */ + uint16_t errintsts; /* Error Interrupt Status Register */ + uint16_t norintstsen; /* Normal Interrupt Status Enable Register */ + uint16_t errintstsen; /* Error Interrupt Status Enable Register */ + uint16_t norintsigen; /* Normal Interrupt Signal Enable Register */ + uint16_t errintsigen; /* Error Interrupt Signal Enable Register */ + uint16_t acmd12errsts; /* Auto CMD12 error status register */ + uint64_t admasysaddr; /* ADMA System Address Register */ + + uint32_t capareg; /* Capabilities Register */ + uint32_t maxcurr; /* Maximum Current Capabilities Register */ + uint8_t *fifo_buffer; /* SD host i/o FIFO buffer */ + uint32_t buf_maxsz; + uint16_t data_count; /* current element in FIFO buffer */ + uint8_t stopped_state;/* Current SDHC state */ + /* Buffer Data Port Register - virtual access point to R and W buffers */ + /* Software Reset Register - always reads as 0 */ + /* Force Event Auto CMD12 Error Interrupt Reg - write only */ + /* Force Event Error Interrupt Register- write only */ + /* RO Host Controller Version Register always reads as 0x2401 */ +} SDHCIState; + +#define TYPE_PCI_SDHCI "sdhci-pci" +#define PCI_SDHCI(obj) OBJECT_CHECK(SDHCIState, (obj), TYPE_PCI_SDHCI) + +#define TYPE_SYSBUS_SDHCI "generic-sdhci" +#define SYSBUS_SDHCI(obj) \ + OBJECT_CHECK(SDHCIState, (obj), TYPE_SYSBUS_SDHCI) + +#endif /* SDHCI_H */ From 33108e9f3388b07b7daa4e46d476ff89ce7dbec5 Mon Sep 17 00:00:00 2001 From: Sai Pavan Boddu Date: Thu, 8 Oct 2015 18:51:03 +0530 Subject: [PATCH 11/12] target-arm: xlnx-zynqmp: Add sdhci support. Add two SYSBUS_SDHCI devices for xlnx-zynqmp Signed-off-by: Sai Pavan Boddu Reviewed-by: Peter Crosthwaite Signed-off-by: Stefan Hajnoczi --- hw/arm/xlnx-zynqmp.c | 28 ++++++++++++++++++++++++++++ include/hw/arm/xlnx-zynqmp.h | 3 +++ 2 files changed, 31 insertions(+) diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c index b36ca3da74..87553bbc60 100644 --- a/hw/arm/xlnx-zynqmp.c +++ b/hw/arm/xlnx-zynqmp.c @@ -48,6 +48,14 @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = { 21, 22, }; +static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = { + 0xFF160000, 0xFF170000, +}; + +static const int sdhci_intr[XLNX_ZYNQMP_NUM_SDHCI] = { + 48, 49, +}; + typedef struct XlnxZynqMPGICRegion { int region_index; uint32_t address; @@ -97,6 +105,13 @@ static void xlnx_zynqmp_init(Object *obj) object_initialize(&s->sata, sizeof(s->sata), TYPE_SYSBUS_AHCI); qdev_set_parent_bus(DEVICE(&s->sata), sysbus_get_default()); + + for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { + object_initialize(&s->sdhci[i], sizeof(s->sdhci[i]), + TYPE_SYSBUS_SDHCI); + qdev_set_parent_bus(DEVICE(&s->sdhci[i]), + sysbus_get_default()); + } } static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) @@ -258,6 +273,19 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp) sysbus_mmio_map(SYS_BUS_DEVICE(&s->sata), 0, SATA_ADDR); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sata), 0, gic_spi[SATA_INTR]); + + for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) { + object_property_set_bool(OBJECT(&s->sdhci[i]), true, + "realized", &err); + if (err) { + error_propagate(errp, err); + return; + } + sysbus_mmio_map(SYS_BUS_DEVICE(&s->sdhci[i]), 0, + sdhci_addr[i]); + sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci[i]), 0, + gic_spi[sdhci_intr[i]]); + } } static Property xlnx_zynqmp_props[] = { diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h index 4005a9960b..d1160920cc 100644 --- a/include/hw/arm/xlnx-zynqmp.h +++ b/include/hw/arm/xlnx-zynqmp.h @@ -24,6 +24,7 @@ #include "hw/char/cadence_uart.h" #include "hw/ide/pci.h" #include "hw/ide/ahci.h" +#include "hw/sd/sdhci.h" #define TYPE_XLNX_ZYNQMP "xlnx,zynqmp" #define XLNX_ZYNQMP(obj) OBJECT_CHECK(XlnxZynqMPState, (obj), \ @@ -33,6 +34,7 @@ #define XLNX_ZYNQMP_NUM_RPU_CPUS 2 #define XLNX_ZYNQMP_NUM_GEMS 4 #define XLNX_ZYNQMP_NUM_UARTS 2 +#define XLNX_ZYNQMP_NUM_SDHCI 2 #define XLNX_ZYNQMP_NUM_OCM_BANKS 4 #define XLNX_ZYNQMP_OCM_RAM_0_ADDRESS 0xFFFC0000 @@ -63,6 +65,7 @@ typedef struct XlnxZynqMPState { CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS]; CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS]; SysbusAHCIState sata; + SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI]; char *boot_cpu; ARMCPU *boot_cpu_ptr; From 37a639a7fbc5c6b065c80e7e2de78d22af735496 Mon Sep 17 00:00:00 2001 From: Kevin Wolf Date: Wed, 28 Oct 2015 11:46:51 +0100 Subject: [PATCH 12/12] block: Consider all child nodes in bdrv_requests_pending() The function manually recursed into bs->file and bs->backing to check whether there were any requests pending, but it ignored other children. There's no need to special case file and backing here, so just replace these two explicit recursions by a loop recursing for all child nodes. Reported-by: Max Reitz Signed-off-by: Kevin Wolf Reviewed-by: Alberto Garcia Reviewed-by: Jeff Cody Message-id: 1446029211-27148-1-git-send-email-kwolf@redhat.com Signed-off-by: Stefan Hajnoczi --- block/io.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/block/io.c b/block/io.c index 5ac6256ad3..8dcad3b3fe 100644 --- a/block/io.c +++ b/block/io.c @@ -216,6 +216,8 @@ void bdrv_disable_copy_on_read(BlockDriverState *bs) /* Check if any requests are in-flight (including throttled requests) */ bool bdrv_requests_pending(BlockDriverState *bs) { + BdrvChild *child; + if (!QLIST_EMPTY(&bs->tracked_requests)) { return true; } @@ -225,12 +227,13 @@ bool bdrv_requests_pending(BlockDriverState *bs) if (!qemu_co_queue_empty(&bs->throttled_reqs[1])) { return true; } - if (bs->file && bdrv_requests_pending(bs->file->bs)) { - return true; - } - if (bs->backing && bdrv_requests_pending(bs->backing->bs)) { - return true; + + QLIST_FOREACH(child, &bs->children, next) { + if (bdrv_requests_pending(child->bs)) { + return true; + } } + return false; }