* [Qemu-devel] [PATCH 1/3] qemugdb: fix licensing
2019-03-11 12:35 [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend Paolo Bonzini
@ 2019-03-11 12:35 ` Paolo Bonzini
2019-03-11 12:35 ` [Qemu-devel] [PATCH 2/3] qemugdb: allow adding support for other coroutine backends Paolo Bonzini
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2019-03-11 12:35 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, kwolf
qemu-gdb.py was committed after 2012-01-13, so the notice about
GPL v2-only contributions does not apply.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
scripts/qemu-gdb.py | 7 ++-----
scripts/qemugdb/coroutine.py | 7 ++-----
scripts/qemugdb/mtree.py | 7 ++-----
scripts/qemugdb/tcg.py | 7 ++-----
4 files changed, 8 insertions(+), 20 deletions(-)
diff --git a/scripts/qemu-gdb.py b/scripts/qemu-gdb.py
index 690827e6fc..f2a305c42e 100644
--- a/scripts/qemu-gdb.py
+++ b/scripts/qemu-gdb.py
@@ -7,11 +7,8 @@
# Authors:
# Avi Kivity <avi@redhat.com>
#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
# Usage:
# At the (gdb) prompt, type "source scripts/qemu-gdb.py".
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 81f811ac00..41e079d0e2 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -7,11 +7,8 @@
# Authors:
# Avi Kivity <avi@redhat.com>
#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# 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
diff --git a/scripts/qemugdb/mtree.py b/scripts/qemugdb/mtree.py
index e6791b7885..3030a60d3f 100644
--- a/scripts/qemugdb/mtree.py
+++ b/scripts/qemugdb/mtree.py
@@ -7,11 +7,8 @@
# Authors:
# Avi Kivity <avi@redhat.com>
#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
# 'qemu mtree' -- display the memory hierarchy
diff --git a/scripts/qemugdb/tcg.py b/scripts/qemugdb/tcg.py
index 8c7f1d7454..18880fc9a7 100644
--- a/scripts/qemugdb/tcg.py
+++ b/scripts/qemugdb/tcg.py
@@ -8,11 +8,8 @@
# Authors:
# Alex Bennée <alex.bennee@linaro.org>
#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-# Contributions after 2012-01-13 are licensed under the terms of the
-# GNU GPL, version 2 or (at your option) any later version.
+# This work is licensed under the terms of the GNU GPL, version 2 or
+# later. See the COPYING file in the top-level directory.
# 'qemu tcg-lock-status' -- display the TCG lock status across threads
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [Qemu-devel] [PATCH 2/3] qemugdb: allow adding support for other coroutine backends
2019-03-11 12:35 [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend Paolo Bonzini
2019-03-11 12:35 ` [Qemu-devel] [PATCH 1/3] qemugdb: fix licensing Paolo Bonzini
@ 2019-03-11 12:35 ` Paolo Bonzini
2019-03-11 12:35 ` [Qemu-devel] [PATCH 3/3] coroutine: add x86 specific coroutine backend Paolo Bonzini
2019-03-11 12:51 ` [Qemu-devel] [PATCH 0/2] " no-reply
3 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2019-03-11 12:35 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, kwolf
Split the jmpbuf access to a separate module and dispatch based
on which CoroutineXYZ type is defined.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
scripts/qemugdb/coroutine.py | 106 ++++++++------------------
scripts/qemugdb/coroutine_ucontext.py | 69 +++++++++++++++++
2 files changed, 100 insertions(+), 75 deletions(-)
create mode 100644 scripts/qemugdb/coroutine_ucontext.py
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index 41e079d0e2..db2753d949 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# GDB debugging support
+# GDB debugging support, coroutine dispatch
#
# Copyright 2012 Red Hat, Inc. and/or its affiliates
#
@@ -10,82 +10,25 @@
# This work is licensed under the terms of the GNU GPL, version 2
# or later. See the COPYING file in the top-level directory.
+from . import coroutine_ucontext
import gdb
VOID_PTR = gdb.lookup_type('void').pointer()
+UINTPTR_T = gdb.lookup_type('uintptr_t')
-def get_fs_base():
- '''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 (int)arch_prctl(0x1003, $rsp - 120)', False, True)
- fs_base = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
- 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 = pthread_self()
- return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base)
-
-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 get_jmpbuf_regs(jmpbuf):
- JB_RBX = 0
- JB_RBP = 1
- JB_R12 = 2
- JB_R13 = 3
- JB_R14 = 4
- JB_R15 = 5
- JB_RSP = 6
- JB_PC = 7
-
- pointer_guard = get_glibc_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')
-
- 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']
+backends = {
+ 'CoroutineUContext': coroutine_ucontext
+}
+def coroutine_backend():
+ for k, v in backends.items():
+ try:
+ gdb.lookup_type(k)
+ except:
+ continue
+ return v
+
+ raise Exception('could not find coroutine backend')
class CoroutineCommand(gdb.Command):
'''Display coroutine backtrace'''
@@ -99,18 +42,31 @@ class CoroutineCommand(gdb.Command):
gdb.write('usage: qemu coroutine <coroutine-pointer>\n')
return
- bt_jmpbuf(coroutine_to_jmpbuf(gdb.parse_and_eval(argv[0])))
+ addr = gdb.parse_and_eval(argv[0])
+ regs = coroutine_backend().get_coroutine_regs(addr)
+ 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].cast(UINTPTR_T)))
+
+ gdb.execute('bt')
+
+ for i in regs:
+ gdb.execute('set $%s = %s' % (i, old[i].cast(UINTPTR_T)))
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)
+ return coroutine_backend().get_coroutine_regs(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)
+ return coroutine_backend().get_coroutine_regs(addr)['rip'].cast(VOID_PTR)
diff --git a/scripts/qemugdb/coroutine_ucontext.py b/scripts/qemugdb/coroutine_ucontext.py
new file mode 100644
index 0000000000..a2f8c1dbbf
--- /dev/null
+++ b/scripts/qemugdb/coroutine_ucontext.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+
+# GDB debugging support
+#
+# Copyright 2012 Red Hat, Inc. and/or its affiliates
+#
+# Authors:
+# Avi Kivity <avi@redhat.com>
+#
+# 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
+
+def get_fs_base():
+ '''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 (int)arch_prctl(0x1003, $rsp - 120)', False, True)
+ fs_base = gdb.parse_and_eval('*(uint64_t*)($rsp - 120)')
+ 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 = pthread_self()
+ return gdb.parse_and_eval('*(uint64_t*)((uint64_t)%s + 0x30)' % fs_base)
+
+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 get_jmpbuf_regs(jmpbuf):
+ JB_RBX = 0
+ JB_RBP = 1
+ JB_R12 = 2
+ JB_R13 = 3
+ JB_R14 = 4
+ JB_R15 = 5
+ JB_RSP = 6
+ JB_PC = 7
+
+ pointer_guard = get_glibc_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 get_coroutine_regs(addr):
+ co = addr.cast(gdb.lookup_type('CoroutineUContext').pointer())
+ return get_jmpbuf_regs(co['env']['__jmpbuf'])
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* [Qemu-devel] [PATCH 3/3] coroutine: add x86 specific coroutine backend
2019-03-11 12:35 [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend Paolo Bonzini
2019-03-11 12:35 ` [Qemu-devel] [PATCH 1/3] qemugdb: fix licensing Paolo Bonzini
2019-03-11 12:35 ` [Qemu-devel] [PATCH 2/3] qemugdb: allow adding support for other coroutine backends Paolo Bonzini
@ 2019-03-11 12:35 ` Paolo Bonzini
2019-03-11 12:51 ` [Qemu-devel] [PATCH 0/2] " no-reply
3 siblings, 0 replies; 5+ messages in thread
From: Paolo Bonzini @ 2019-03-11 12:35 UTC (permalink / raw)
To: qemu-devel; +Cc: qemu-block, kwolf
This backend is faster (100ns vs 150ns per switch on my laptop), but
especially it will be possible to add CET support to it in 4.1. In
the meanwhile, it is nice to have it as an experimental alternative.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
configure | 8 ++
scripts/qemugdb/coroutine.py | 5 +-
scripts/qemugdb/coroutine_x86.py | 21 +++
util/coroutine-x86.c | 213 +++++++++++++++++++++++++++++++
4 files changed, 245 insertions(+), 2 deletions(-)
create mode 100644 scripts/qemugdb/coroutine_x86.py
create mode 100644 util/coroutine-x86.c
diff --git a/configure b/configure
index 62a2a490f2..af65edc30a 100755
--- a/configure
+++ b/configure
@@ -5123,6 +5123,14 @@ else
error_exit "only the 'windows' coroutine backend is valid for Windows"
fi
;;
+ x86)
+ if test "$mingw32" = "yes"; then
+ error_exit "only the 'windows' coroutine backend is valid for Windows"
+ fi
+ if test "$cpu" != "x86_64"; then
+ error_exit "the 'x86' backend is only valid for x86_64 hosts"
+ fi
+ ;;
*)
error_exit "unknown coroutine backend $coroutine"
;;
diff --git a/scripts/qemugdb/coroutine.py b/scripts/qemugdb/coroutine.py
index db2753d949..f716db22bb 100644
--- a/scripts/qemugdb/coroutine.py
+++ b/scripts/qemugdb/coroutine.py
@@ -10,14 +10,15 @@
# This work is licensed under the terms of the GNU GPL, version 2
# or later. See the COPYING file in the top-level directory.
-from . import coroutine_ucontext
+from . import coroutine_ucontext, coroutine_x86
import gdb
VOID_PTR = gdb.lookup_type('void').pointer()
UINTPTR_T = gdb.lookup_type('uintptr_t')
backends = {
- 'CoroutineUContext': coroutine_ucontext
+ 'CoroutineUContext': coroutine_ucontext,
+ 'CoroutineX86': coroutine_x86
}
def coroutine_backend():
diff --git a/scripts/qemugdb/coroutine_x86.py b/scripts/qemugdb/coroutine_x86.py
new file mode 100644
index 0000000000..05f830cdb8
--- /dev/null
+++ b/scripts/qemugdb/coroutine_x86.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+# GDB debugging support
+#
+# Copyright 2019 Red Hat, Inc.
+#
+# Authors:
+# Paolo Bonzini <pbonzini@redhat.com>
+#
+# 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
+
+U64_PTR = gdb.lookup_type('uint64_t').pointer()
+
+def get_coroutine_regs(addr):
+ addr = addr.cast(gdb.lookup_type('CoroutineX86').pointer())
+ rsp = addr['sp'].cast(U64_PTR)
+ return {'rsp': rsp,
+ 'rip': rsp.dereference()}
diff --git a/util/coroutine-x86.c b/util/coroutine-x86.c
new file mode 100644
index 0000000000..7f5e7d7696
--- /dev/null
+++ b/util/coroutine-x86.c
@@ -0,0 +1,213 @@
+/*
+ * x86-specific coroutine initialization code
+ *
+ * Copyright (C) 2006 Anthony Liguori <anthony@codemonkey.ws>
+ * Copyright (C) 2011 Kevin Wolf <kwolf@redhat.com>
+ * Copyright (C) 2019 Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.0 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* XXX Is there a nicer way to disable glibc's stack check for longjmp? */
+#ifdef _FORTIFY_SOURCE
+#undef _FORTIFY_SOURCE
+#endif
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/coroutine_int.h"
+
+#ifdef CONFIG_VALGRIND_H
+#include <valgrind/valgrind.h>
+#endif
+
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
+#ifdef CONFIG_ASAN_IFACE_FIBER
+#define CONFIG_ASAN 1
+#include <sanitizer/asan_interface.h>
+#endif
+#endif
+
+typedef struct {
+ Coroutine base;
+ void *stack;
+ size_t stack_size;
+ void *sp;
+
+#ifdef CONFIG_VALGRIND_H
+ unsigned int valgrind_stack_id;
+#endif
+} CoroutineX86;
+
+/**
+ * Per-thread coroutine bookkeeping
+ */
+static __thread CoroutineX86 leader;
+static __thread Coroutine *current;
+
+static void finish_switch_fiber(void *fake_stack_save)
+{
+#ifdef CONFIG_ASAN
+ const void *bottom_old;
+ size_t size_old;
+
+ __sanitizer_finish_switch_fiber(fake_stack_save, &bottom_old, &size_old);
+
+ if (!leader.stack) {
+ leader.stack = (void *)bottom_old;
+ leader.stack_size = size_old;
+ }
+#endif
+}
+
+static void start_switch_fiber(void **fake_stack_save,
+ const void *bottom, size_t size)
+{
+#ifdef CONFIG_ASAN
+ __sanitizer_start_switch_fiber(fake_stack_save, bottom, size);
+#endif
+}
+
+/* On entry to a coroutine, rax is "value" and rsi is the coroutine itself. */
+#define CO_SWITCH(from, to, action, jump) ({ \
+ int ret = action; \
+ void *from_ = from; \
+ void *to_ = to; \
+ asm volatile( \
+ ".cfi_remember_state\n" \
+ "pushq %%rbp\n" /* save scratch register on source stack */ \
+ ".cfi_adjust_cfa_offset 8\n" \
+ ".cfi_rel_offset %%rbp, 0\n" \
+ "call 1f\n" /* switch continues at label 1 */ \
+ ".cfi_adjust_cfa_offset 8\n" \
+ "jmp 2f\n" /* switch back continues at label 2 */ \
+ "1: movq (%%rsp), %%rbp\n" /* save source IP for debugging */ \
+ "movq %%rsp, %c[sp](%[FROM])\n" /* save source SP */ \
+ "movq %c[sp](%[TO]), %%rsp\n" /* load destination SP */ \
+ jump "\n" /* coroutine switch */ \
+ "2:" \
+ ".cfi_adjust_cfa_offset -8\n" \
+ "popq %%rbp\n" \
+ ".cfi_adjust_cfa_offset -8\n" \
+ ".cfi_restore_state\n" \
+ : "+a" (ret), [FROM] "+b" (from_), [TO] "+D" (to_) \
+ : [sp] "i" (offsetof(CoroutineX86, sp)) \
+ : "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
+ "memory"); \
+ ret; \
+})
+
+static void __attribute__((__used__)) coroutine_trampoline(void *arg)
+{
+ CoroutineX86 *self = arg;
+ Coroutine *co = &self->base;
+
+ finish_switch_fiber(NULL);
+
+ while (true) {
+ qemu_coroutine_switch(co, co->caller, COROUTINE_TERMINATE);
+ co->entry(co->entry_arg);
+ }
+}
+
+Coroutine *qemu_coroutine_new(void)
+{
+ CoroutineX86 *co;
+ void *fake_stack_save = NULL;
+
+ co = g_malloc0(sizeof(*co));
+ co->stack_size = COROUTINE_STACK_SIZE;
+ co->stack = qemu_alloc_stack(&co->stack_size);
+ co->sp = co->stack + co->stack_size;
+
+#ifdef CONFIG_VALGRIND_H
+ co->valgrind_stack_id =
+ VALGRIND_STACK_REGISTER(co->stack, co->stack + co->stack_size);
+#endif
+
+ /* Immediately enter the coroutine once to pass it its address as the argument */
+ co->base.caller = qemu_coroutine_self();
+ start_switch_fiber(&fake_stack_save, co->stack, co->stack_size);
+ CO_SWITCH(current, co, 0, "jmp coroutine_trampoline");
+ finish_switch_fiber(fake_stack_save);
+ co->base.caller = NULL;
+
+ return &co->base;
+}
+
+#ifdef CONFIG_VALGRIND_H
+#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__)
+/* Work around an unused variable in the valgrind.h macro... */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
+#endif
+static inline void valgrind_stack_deregister(CoroutineX86 *co)
+{
+ VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
+}
+#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+#endif
+
+void qemu_coroutine_delete(Coroutine *co_)
+{
+ CoroutineX86 *co = DO_UPCAST(CoroutineX86, base, co_);
+
+#ifdef CONFIG_VALGRIND_H
+ valgrind_stack_deregister(co);
+#endif
+
+ qemu_free_stack(co->stack, co->stack_size);
+ g_free(co);
+}
+
+/*
+ * This function is marked noinline to prevent GCC from inlining it
+ * into coroutine_trampoline(). If we allow it to do that then it
+ * hoists the code to get the address of the TLS variable "current"
+ * out of the while() loop. This is an invalid transformation because
+ * qemu_coroutine_switch() may be called when running thread A but
+ * return in thread B, and so we might be in a different thread
+ * context each time round the loop.
+ */
+CoroutineAction __attribute__((noinline))
+qemu_coroutine_switch(Coroutine *from_, Coroutine *to_,
+ CoroutineAction action)
+{
+ CoroutineX86 *from = DO_UPCAST(CoroutineX86, base, from_);
+ CoroutineX86 *to = DO_UPCAST(CoroutineX86, base, to_);
+ void *fake_stack_save = NULL;
+
+ current = to_;
+
+ start_switch_fiber(action == COROUTINE_TERMINATE ?
+ NULL : &fake_stack_save, to->stack, to->stack_size);
+ action = CO_SWITCH(from, to, action, "ret");
+ finish_switch_fiber(fake_stack_save);
+
+ return action;
+}
+
+Coroutine *qemu_coroutine_self(void)
+{
+ if (!current) {
+ current = &leader.base;
+ }
+ return current;
+}
+
+bool qemu_in_coroutine(void)
+{
+ return current && current->caller;
+}
--
2.20.1
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend
2019-03-11 12:35 [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend Paolo Bonzini
` (2 preceding siblings ...)
2019-03-11 12:35 ` [Qemu-devel] [PATCH 3/3] coroutine: add x86 specific coroutine backend Paolo Bonzini
@ 2019-03-11 12:51 ` no-reply
3 siblings, 0 replies; 5+ messages in thread
From: no-reply @ 2019-03-11 12:51 UTC (permalink / raw)
To: pbonzini; +Cc: fam, qemu-devel, kwolf, qemu-block
Patchew URL: https://patchew.org/QEMU/20190311123507.24867-1-pbonzini@redhat.com/
Hi,
This series seems to have some coding style problems. See output below for
more information:
Type: series
Message-id: 20190311123507.24867-1-pbonzini@redhat.com
Subject: [Qemu-devel] [PATCH 0/2] coroutine: add x86 specific coroutine backend
=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===
Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
e2a18635a4..336cfef495 master -> master
* [new tag] patchew/20190311123507.24867-1-pbonzini@redhat.com -> patchew/20190311123507.24867-1-pbonzini@redhat.com
Switched to a new branch 'test'
e241487774 coroutine: add x86 specific coroutine backend
5b3b779548 qemugdb: allow adding support for other coroutine backends
83841cb732 qemugdb: fix licensing
=== OUTPUT BEGIN ===
1/3 Checking commit 83841cb73288 (qemugdb: fix licensing)
2/3 Checking commit 5b3b77954837 (qemugdb: allow adding support for other coroutine backends)
WARNING: line over 80 characters
#147: FILE: scripts/qemugdb/coroutine.py:65:
+ return coroutine_backend().get_coroutine_regs(addr)['rsp'].cast(VOID_PTR)
WARNING: line over 80 characters
#155: FILE: scripts/qemugdb/coroutine.py:72:
+ return coroutine_backend().get_coroutine_regs(addr)['rip'].cast(VOID_PTR)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#157:
new file mode 100644
ERROR: line over 90 characters
#206: FILE: scripts/qemugdb/coroutine_ucontext.py:45:
+ return gdb.parse_and_eval('(((uint64_t)%s >> 0x11) | ((uint64_t)%s << (64 - 0x11))) ^ (uint64_t)%s' % (val, val, pointer_guard))
total: 1 errors, 3 warnings, 205 lines checked
Patch 2/3 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/3 Checking commit e24148777414 (coroutine: add x86 specific coroutine backend)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#56:
new file mode 100644
WARNING: architecture specific defines should be avoided
#121: FILE: util/coroutine-x86.c:34:
+#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)
WARNING: line over 80 characters
#169: FILE: util/coroutine-x86.c:82:
+#define CO_SWITCH(from, to, action, jump) ({ \
WARNING: line over 80 characters
#170: FILE: util/coroutine-x86.c:83:
+ int ret = action; \
WARNING: line over 80 characters
#171: FILE: util/coroutine-x86.c:84:
+ void *from_ = from; \
WARNING: line over 80 characters
#172: FILE: util/coroutine-x86.c:85:
+ void *to_ = to; \
WARNING: line over 80 characters
#173: FILE: util/coroutine-x86.c:86:
+ asm volatile( \
WARNING: line over 80 characters
#174: FILE: util/coroutine-x86.c:87:
+ ".cfi_remember_state\n" \
WARNING: line over 80 characters
#175: FILE: util/coroutine-x86.c:88:
+ "pushq %%rbp\n" /* save scratch register on source stack */ \
WARNING: Block comments use a leading /* on a separate line
#175: FILE: util/coroutine-x86.c:88:
+ "pushq %%rbp\n" /* save scratch register on source stack */ \
WARNING: line over 80 characters
#176: FILE: util/coroutine-x86.c:89:
+ ".cfi_adjust_cfa_offset 8\n" \
WARNING: line over 80 characters
#177: FILE: util/coroutine-x86.c:90:
+ ".cfi_rel_offset %%rbp, 0\n" \
WARNING: line over 80 characters
#178: FILE: util/coroutine-x86.c:91:
+ "call 1f\n" /* switch continues at label 1 */ \
WARNING: Block comments use a leading /* on a separate line
#178: FILE: util/coroutine-x86.c:91:
+ "call 1f\n" /* switch continues at label 1 */ \
WARNING: line over 80 characters
#179: FILE: util/coroutine-x86.c:92:
+ ".cfi_adjust_cfa_offset 8\n" \
WARNING: line over 80 characters
#180: FILE: util/coroutine-x86.c:93:
+ "jmp 2f\n" /* switch back continues at label 2 */ \
WARNING: Block comments use a leading /* on a separate line
#180: FILE: util/coroutine-x86.c:93:
+ "jmp 2f\n" /* switch back continues at label 2 */ \
WARNING: line over 80 characters
#181: FILE: util/coroutine-x86.c:94:
+ "1: movq (%%rsp), %%rbp\n" /* save source IP for debugging */ \
WARNING: Block comments use a leading /* on a separate line
#181: FILE: util/coroutine-x86.c:94:
+ "1: movq (%%rsp), %%rbp\n" /* save source IP for debugging */ \
WARNING: line over 80 characters
#182: FILE: util/coroutine-x86.c:95:
+ "movq %%rsp, %c[sp](%[FROM])\n" /* save source SP */ \
WARNING: Block comments use a leading /* on a separate line
#182: FILE: util/coroutine-x86.c:95:
+ "movq %%rsp, %c[sp](%[FROM])\n" /* save source SP */ \
WARNING: line over 80 characters
#183: FILE: util/coroutine-x86.c:96:
+ "movq %c[sp](%[TO]), %%rsp\n" /* load destination SP */ \
WARNING: Block comments use a leading /* on a separate line
#183: FILE: util/coroutine-x86.c:96:
+ "movq %c[sp](%[TO]), %%rsp\n" /* load destination SP */ \
WARNING: line over 80 characters
#184: FILE: util/coroutine-x86.c:97:
+ jump "\n" /* coroutine switch */ \
WARNING: Block comments use a leading /* on a separate line
#184: FILE: util/coroutine-x86.c:97:
+ jump "\n" /* coroutine switch */ \
WARNING: line over 80 characters
#185: FILE: util/coroutine-x86.c:98:
+ "2:" \
WARNING: line over 80 characters
#186: FILE: util/coroutine-x86.c:99:
+ ".cfi_adjust_cfa_offset -8\n" \
WARNING: line over 80 characters
#187: FILE: util/coroutine-x86.c:100:
+ "popq %%rbp\n" \
WARNING: line over 80 characters
#188: FILE: util/coroutine-x86.c:101:
+ ".cfi_adjust_cfa_offset -8\n" \
WARNING: line over 80 characters
#189: FILE: util/coroutine-x86.c:102:
+ ".cfi_restore_state\n" \
WARNING: line over 80 characters
#190: FILE: util/coroutine-x86.c:103:
+ : "+a" (ret), [FROM] "+b" (from_), [TO] "+D" (to_) \
WARNING: line over 80 characters
#191: FILE: util/coroutine-x86.c:104:
+ : [sp] "i" (offsetof(CoroutineX86, sp)) \
WARNING: line over 80 characters
#192: FILE: util/coroutine-x86.c:105:
+ : "rcx", "rdx", "rsi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", \
WARNING: line over 80 characters
#193: FILE: util/coroutine-x86.c:106:
+ "memory"); \
WARNING: line over 80 characters
#225: FILE: util/coroutine-x86.c:138:
+ /* Immediately enter the coroutine once to pass it its address as the argument */
WARNING: architecture specific defines should be avoided
#236: FILE: util/coroutine-x86.c:149:
+#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__)
WARNING: architecture specific defines should be avoided
#245: FILE: util/coroutine-x86.c:158:
+#if defined(CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE) && !defined(__clang__)
total: 0 errors, 37 warnings, 265 lines checked
Patch 3/3 has style problems, please review. If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
=== OUTPUT END ===
Test command exited with code: 1
The full log is available at
http://patchew.org/logs/20190311123507.24867-1-pbonzini@redhat.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [http://patchew.org/].
Please send your feedback to patchew-devel@redhat.com
^ permalink raw reply [flat|nested] 5+ messages in thread