Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* Support for jemalloc
* qemu_mutex_lock_iothread "No such process" fix
* cutils: qemu_strto* wrappers
* iohandler.c simplification
* Many other fixes and misc patches.

And some MTTCG work (with Emilio's fixes squashed):
* Signal-free TCG kick
* Removing spinlock in favor of QemuMutex
* User-mode emulation multi-threading fixes/docs

# gpg: Signature made Thu 10 Sep 2015 09:03:07 BST using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"

* remotes/bonzini/tags/for-upstream: (44 commits)
  cutils: work around platform differences in strto{l,ul,ll,ull}
  cpu-exec: fix lock hierarchy for user-mode emulation
  exec: make mmap_lock/mmap_unlock globally available
  tcg: comment on which functions have to be called with mmap_lock held
  tcg: add memory barriers in page_find_alloc accesses
  remove unused spinlock.
  replace spinlock by QemuMutex.
  cpus: remove tcg_halt_cond and tcg_cpu_thread globals
  cpus: protect work list with work_mutex
  scripts/dump-guest-memory.py: fix after RAMBlock change
  configure: Add support for jemalloc
  add macro file for coccinelle
  configure: factor out adding disas configure
  vhost-scsi: fix wrong vhost-scsi firmware path
  checkpatch: remove tests that are not relevant outside the kernel
  checkpatch: adapt some tests to QEMU
  CODING_STYLE: update mixed declaration rules
  qmp: Add example usage of strto*l() qemu wrapper
  cutils: Add qemu_strtoull() wrapper
  cutils: Add qemu_strtoll() wrapper
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2015-09-14 16:13:16 +01:00
56 changed files with 2049 additions and 1043 deletions
+9 -4
View File
@@ -87,10 +87,15 @@ Furthermore, it is the QEMU coding style.
5. Declarations
Mixed declarations (interleaving statements and declarations within blocks)
are not allowed; declarations should be at the beginning of blocks. In other
words, the code should not generate warnings if using GCC's
-Wdeclaration-after-statement option.
Mixed declarations (interleaving statements and declarations within
blocks) are generally not allowed; declarations should be at the beginning
of blocks.
Every now and then, an exception is made for declarations inside a
#ifdef or #ifndef block: if the code looks nicer, such declarations can
be placed at the top of the block even if there are statements above.
On the other hand, however, it's often best to move that #ifdef/#ifndef
block to a separate function altogether.
6. Conditional statements
+1 -1
View File
@@ -7,7 +7,7 @@ include config-target.mak
include config-devices.mak
include $(SRC_PATH)/rules.mak
$(call set-vpath, $(SRC_PATH))
$(call set-vpath, $(SRC_PATH):$(BUILD_DIR))
ifdef CONFIG_LINUX
QEMU_CFLAGS += -I../linux-headers
endif
+4
View File
@@ -1214,6 +1214,10 @@ static void iscsi_readcapacity_sync(IscsiLun *iscsilun, Error **errp)
if (task == NULL || task->status != SCSI_STATUS_GOOD) {
error_setg(errp, "iSCSI: failed to send readcapacity10 command.");
} else if (!iscsilun->block_size ||
iscsilun->block_size % BDRV_SECTOR_SIZE) {
error_setg(errp, "iSCSI: the target returned an invalid "
"block size of %d.", iscsilun->block_size);
}
if (task) {
scsi_free_scsi_task(task);
-2
View File
@@ -211,8 +211,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
abi_ulong new_addr);
int target_msync(abi_ulong start, abi_ulong len, int flags);
extern unsigned long last_brk;
void mmap_lock(void);
void mmap_unlock(void);
void cpu_list_lock(void);
void cpu_list_unlock(void);
#if defined(CONFIG_USE_NPTL)
Vendored
+53 -40
View File
@@ -337,6 +337,7 @@ libssh2=""
vhdx=""
numa=""
tcmalloc="no"
jemalloc="no"
# parse CC options first
for opt do
@@ -1143,6 +1144,10 @@ for opt do
;;
--enable-tcmalloc) tcmalloc="yes"
;;
--disable-jemalloc) jemalloc="no"
;;
--enable-jemalloc) jemalloc="yes"
;;
*)
echo "ERROR: unknown option $opt"
echo "Try '$0 --help' for more information"
@@ -1367,6 +1372,7 @@ disabled with --disable-FEATURE, default is enabled if available:
vhdx support for the Microsoft VHDX image format
numa libnuma support
tcmalloc tcmalloc support
jemalloc jemalloc support
NOTE: The object files are built at the place where configure is launched
EOF
@@ -3395,6 +3401,11 @@ EOF
fi
fi
if test "$tcmalloc" = "yes" && test "$jemalloc" = "yes" ; then
echo "ERROR: tcmalloc && jemalloc can't be used at the same time"
exit 1
fi
##########################################
# tcmalloc probe
@@ -3411,6 +3422,22 @@ EOF
fi
fi
##########################################
# jemalloc probe
if test "$jemalloc" = "yes" ; then
cat > $TMPC << EOF
#include <stdlib.h>
int main(void) { malloc(1); return 0; }
EOF
if compile_prog "" "-ljemalloc" ; then
LIBS="-ljemalloc $LIBS"
else
feature_not_found "jemalloc" "install jemalloc devel"
fi
fi
##########################################
# signalfd probe
signalfd="no"
@@ -4629,6 +4656,7 @@ echo "snappy support $snappy"
echo "bzip2 support $bzip2"
echo "NUMA host support $numa"
echo "tcmalloc support $tcmalloc"
echo "jemalloc support $jemalloc"
if test "$sdl_too_old" = "yes"; then
echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -5519,91 +5547,76 @@ fi
cflags=""
ldflags=""
disas_config() {
echo "CONFIG_${1}_DIS=y" >> $config_target_mak
echo "CONFIG_${1}_DIS=y" >> config-all-disas.mak
}
for i in $ARCH $TARGET_BASE_ARCH ; do
case "$i" in
alpha)
echo "CONFIG_ALPHA_DIS=y" >> $config_target_mak
echo "CONFIG_ALPHA_DIS=y" >> config-all-disas.mak
disas_config "ALPHA"
;;
aarch64)
if test -n "${cxx}"; then
echo "CONFIG_ARM_A64_DIS=y" >> $config_target_mak
echo "CONFIG_ARM_A64_DIS=y" >> config-all-disas.mak
disas_config "ARM_A64"
fi
;;
arm)
echo "CONFIG_ARM_DIS=y" >> $config_target_mak
echo "CONFIG_ARM_DIS=y" >> config-all-disas.mak
disas_config "ARM"
if test -n "${cxx}"; then
echo "CONFIG_ARM_A64_DIS=y" >> $config_target_mak
echo "CONFIG_ARM_A64_DIS=y" >> config-all-disas.mak
disas_config "ARM_A64"
fi
;;
cris)
echo "CONFIG_CRIS_DIS=y" >> $config_target_mak
echo "CONFIG_CRIS_DIS=y" >> config-all-disas.mak
disas_config "CRIS"
;;
hppa)
echo "CONFIG_HPPA_DIS=y" >> $config_target_mak
echo "CONFIG_HPPA_DIS=y" >> config-all-disas.mak
disas_config "HPPA"
;;
i386|x86_64|x32)
echo "CONFIG_I386_DIS=y" >> $config_target_mak
echo "CONFIG_I386_DIS=y" >> config-all-disas.mak
disas_config "I386"
;;
ia64*)
echo "CONFIG_IA64_DIS=y" >> $config_target_mak
echo "CONFIG_IA64_DIS=y" >> config-all-disas.mak
disas_config "IA64"
;;
lm32)
echo "CONFIG_LM32_DIS=y" >> $config_target_mak
echo "CONFIG_LM32_DIS=y" >> config-all-disas.mak
disas_config "LM32"
;;
m68k)
echo "CONFIG_M68K_DIS=y" >> $config_target_mak
echo "CONFIG_M68K_DIS=y" >> config-all-disas.mak
disas_config "M68K"
;;
microblaze*)
echo "CONFIG_MICROBLAZE_DIS=y" >> $config_target_mak
echo "CONFIG_MICROBLAZE_DIS=y" >> config-all-disas.mak
disas_config "MICROBLAZE"
;;
mips*)
echo "CONFIG_MIPS_DIS=y" >> $config_target_mak
echo "CONFIG_MIPS_DIS=y" >> config-all-disas.mak
disas_config "MIPS"
;;
moxie*)
echo "CONFIG_MOXIE_DIS=y" >> $config_target_mak
echo "CONFIG_MOXIE_DIS=y" >> config-all-disas.mak
disas_config "MOXIE"
;;
or32)
echo "CONFIG_OPENRISC_DIS=y" >> $config_target_mak
echo "CONFIG_OPENRISC_DIS=y" >> config-all-disas.mak
disas_config "OPENRISC"
;;
ppc*)
echo "CONFIG_PPC_DIS=y" >> $config_target_mak
echo "CONFIG_PPC_DIS=y" >> config-all-disas.mak
disas_config "PPC"
;;
s390*)
echo "CONFIG_S390_DIS=y" >> $config_target_mak
echo "CONFIG_S390_DIS=y" >> config-all-disas.mak
disas_config "S390"
;;
sh4)
echo "CONFIG_SH4_DIS=y" >> $config_target_mak
echo "CONFIG_SH4_DIS=y" >> config-all-disas.mak
disas_config "SH4"
;;
sparc*)
echo "CONFIG_SPARC_DIS=y" >> $config_target_mak
echo "CONFIG_SPARC_DIS=y" >> config-all-disas.mak
disas_config "SPARC"
;;
xtensa*)
echo "CONFIG_XTENSA_DIS=y" >> $config_target_mak
echo "CONFIG_XTENSA_DIS=y" >> config-all-disas.mak
disas_config "XTENSA"
;;
esac
done
if test "$tcg_interpreter" = "yes" ; then
echo "CONFIG_TCI_DIS=y" >> $config_target_mak
echo "CONFIG_TCI_DIS=y" >> config-all-disas.mak
disas_config "TCI"
fi
case "$ARCH" in
+70 -49
View File
@@ -258,10 +258,10 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles,
tb_free(tb);
}
static TranslationBlock *tb_find_slow(CPUState *cpu,
target_ulong pc,
target_ulong cs_base,
uint64_t flags)
static TranslationBlock *tb_find_physical(CPUState *cpu,
target_ulong pc,
target_ulong cs_base,
uint64_t flags)
{
CPUArchState *env = (CPUArchState *)cpu->env_ptr;
TranslationBlock *tb, **ptb1;
@@ -278,8 +278,9 @@ static TranslationBlock *tb_find_slow(CPUState *cpu,
ptb1 = &tcg_ctx.tb_ctx.tb_phys_hash[h];
for(;;) {
tb = *ptb1;
if (!tb)
goto not_found;
if (!tb) {
return NULL;
}
if (tb->pc == pc &&
tb->page_addr[0] == phys_page1 &&
tb->cs_base == cs_base &&
@@ -291,25 +292,59 @@ static TranslationBlock *tb_find_slow(CPUState *cpu,
virt_page2 = (pc & TARGET_PAGE_MASK) +
TARGET_PAGE_SIZE;
phys_page2 = get_page_addr_code(env, virt_page2);
if (tb->page_addr[1] == phys_page2)
goto found;
if (tb->page_addr[1] == phys_page2) {
break;
}
} else {
goto found;
break;
}
}
ptb1 = &tb->phys_hash_next;
}
not_found:
/* if no translated code available, then translate it now */
/* Move the TB to the head of the list */
*ptb1 = tb->phys_hash_next;
tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
return tb;
}
static TranslationBlock *tb_find_slow(CPUState *cpu,
target_ulong pc,
target_ulong cs_base,
uint64_t flags)
{
TranslationBlock *tb;
tb = tb_find_physical(cpu, pc, cs_base, flags);
if (tb) {
goto found;
}
#ifdef CONFIG_USER_ONLY
/* mmap_lock is needed by tb_gen_code, and mmap_lock must be
* taken outside tb_lock. Since we're momentarily dropping
* tb_lock, there's a chance that our desired tb has been
* translated.
*/
tb_unlock();
mmap_lock();
tb_lock();
tb = tb_find_physical(cpu, pc, cs_base, flags);
if (tb) {
mmap_unlock();
goto found;
}
#endif
/* if no translated code available, then translate it now */
tb = tb_gen_code(cpu, pc, cs_base, flags, 0);
found:
/* Move the last found TB to the head of the list */
if (likely(*ptb1)) {
*ptb1 = tb->phys_hash_next;
tb->phys_hash_next = tcg_ctx.tb_ctx.tb_phys_hash[h];
tcg_ctx.tb_ctx.tb_phys_hash[h] = tb;
}
#ifdef CONFIG_USER_ONLY
mmap_unlock();
#endif
found:
/* we add the TB in the virtual pc hash table */
cpu->tb_jmp_cache[tb_jmp_cache_hash_func(pc)] = tb;
return tb;
@@ -350,7 +385,8 @@ static void cpu_handle_debug_exception(CPUState *cpu)
/* main execution loop */
volatile sig_atomic_t exit_request;
bool exit_request;
CPUState *tcg_current_cpu;
int cpu_exec(CPUState *cpu)
{
@@ -365,9 +401,6 @@ int cpu_exec(CPUState *cpu)
uintptr_t next_tb;
SyncClocks sc;
/* This must be volatile so it is not trashed by longjmp() */
volatile bool have_tb_lock = false;
if (cpu->halted) {
if (!cpu_has_work(cpu)) {
return EXCP_HALTED;
@@ -377,18 +410,10 @@ int cpu_exec(CPUState *cpu)
}
current_cpu = cpu;
/* As long as current_cpu is null, up to the assignment just above,
* requests by other threads to exit the execution loop are expected to
* be issued using the exit_request global. We must make sure that our
* evaluation of the global value is performed past the current_cpu
* value transition point, which requires a memory barrier as well as
* an instruction scheduling constraint on modern architectures. */
smp_mb();
atomic_mb_set(&tcg_current_cpu, cpu);
rcu_read_lock();
if (unlikely(exit_request)) {
if (unlikely(atomic_mb_read(&exit_request))) {
cpu->exit_request = 1;
}
@@ -484,8 +509,7 @@ int cpu_exec(CPUState *cpu)
cpu->exception_index = EXCP_INTERRUPT;
cpu_loop_exit(cpu);
}
spin_lock(&tcg_ctx.tb_ctx.tb_lock);
have_tb_lock = true;
tb_lock();
tb = tb_find_fast(cpu);
/* Note: we do it here to avoid a gcc bug on Mac OS X when
doing it in tb_find_slow */
@@ -507,20 +531,14 @@ int cpu_exec(CPUState *cpu)
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
next_tb & TB_EXIT_MASK, tb);
}
have_tb_lock = false;
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
/* cpu_interrupt might be called while translating the
TB, but before it is linked into a potentially
infinite loop and becomes env->current_tb. Avoid
starting execution if there is a pending interrupt. */
cpu->current_tb = tb;
barrier();
tb_unlock();
if (likely(!cpu->exit_request)) {
trace_exec_tb(tb, tb->pc);
tc_ptr = tb->tc_ptr;
/* execute the generated code */
cpu->current_tb = tb;
next_tb = cpu_tb_exec(cpu, tc_ptr);
cpu->current_tb = NULL;
switch (next_tb & TB_EXIT_MASK) {
case TB_EXIT_REQUESTED:
/* Something asked us to stop executing
@@ -528,8 +546,12 @@ int cpu_exec(CPUState *cpu)
* loop. Whatever requested the exit will also
* have set something else (eg exit_request or
* interrupt_request) which we will handle
* next time around the loop.
* next time around the loop. But we need to
* ensure the tcg_exit_req read in generated code
* comes before the next read of cpu->exit_request
* or cpu->interrupt_request.
*/
smp_rmb();
next_tb = 0;
break;
case TB_EXIT_ICOUNT_EXPIRED:
@@ -559,7 +581,6 @@ int cpu_exec(CPUState *cpu)
break;
}
}
cpu->current_tb = NULL;
/* Try to align the host and virtual clocks
if the guest is in advance */
align_clocks(&sc, cpu);
@@ -576,10 +597,7 @@ int cpu_exec(CPUState *cpu)
x86_cpu = X86_CPU(cpu);
env = &x86_cpu->env;
#endif
if (have_tb_lock) {
spin_unlock(&tcg_ctx.tb_ctx.tb_lock);
have_tb_lock = false;
}
tb_lock_reset();
}
} /* for(;;) */
@@ -588,5 +606,8 @@ int cpu_exec(CPUState *cpu)
/* fail safe : never use current_cpu outside cpu_exec() */
current_cpu = NULL;
/* Does not need atomic_mb_set because a spurious wakeup is okay. */
atomic_set(&tcg_current_cpu, NULL);
return ret;
}
+52 -80
View File
@@ -661,14 +661,6 @@ static void cpu_handle_guest_debug(CPUState *cpu)
cpu->stopped = true;
}
static void cpu_signal(int sig)
{
if (current_cpu) {
cpu_exit(current_cpu);
}
exit_request = 1;
}
#ifdef CONFIG_LINUX
static void sigbus_reraise(void)
{
@@ -781,29 +773,11 @@ static void qemu_kvm_init_cpu_signals(CPUState *cpu)
}
}
static void qemu_tcg_init_cpu_signals(void)
{
sigset_t set;
struct sigaction sigact;
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = cpu_signal;
sigaction(SIG_IPI, &sigact, NULL);
sigemptyset(&set);
sigaddset(&set, SIG_IPI);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
}
#else /* _WIN32 */
static void qemu_kvm_init_cpu_signals(CPUState *cpu)
{
abort();
}
static void qemu_tcg_init_cpu_signals(void)
{
}
#endif /* _WIN32 */
static QemuMutex qemu_global_mutex;
@@ -812,9 +786,6 @@ static unsigned iothread_requesting_mutex;
static QemuThread io_thread;
static QemuThread *tcg_cpu_thread;
static QemuCond *tcg_halt_cond;
/* cpu creation */
static QemuCond qemu_cpu_cond;
/* system init */
@@ -845,6 +816,8 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
wi.func = func;
wi.data = data;
wi.free = false;
qemu_mutex_lock(&cpu->work_mutex);
if (cpu->queued_work_first == NULL) {
cpu->queued_work_first = &wi;
} else {
@@ -853,9 +826,10 @@ void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
cpu->queued_work_last = &wi;
wi.next = NULL;
wi.done = false;
qemu_mutex_unlock(&cpu->work_mutex);
qemu_cpu_kick(cpu);
while (!wi.done) {
while (!atomic_mb_read(&wi.done)) {
CPUState *self_cpu = current_cpu;
qemu_cond_wait(&qemu_work_cond, &qemu_global_mutex);
@@ -876,6 +850,8 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
wi->func = func;
wi->data = data;
wi->free = true;
qemu_mutex_lock(&cpu->work_mutex);
if (cpu->queued_work_first == NULL) {
cpu->queued_work_first = wi;
} else {
@@ -884,6 +860,7 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
cpu->queued_work_last = wi;
wi->next = NULL;
wi->done = false;
qemu_mutex_unlock(&cpu->work_mutex);
qemu_cpu_kick(cpu);
}
@@ -896,15 +873,23 @@ static void flush_queued_work(CPUState *cpu)
return;
}
while ((wi = cpu->queued_work_first)) {
qemu_mutex_lock(&cpu->work_mutex);
while (cpu->queued_work_first != NULL) {
wi = cpu->queued_work_first;
cpu->queued_work_first = wi->next;
if (!cpu->queued_work_first) {
cpu->queued_work_last = NULL;
}
qemu_mutex_unlock(&cpu->work_mutex);
wi->func(wi->data);
wi->done = true;
qemu_mutex_lock(&cpu->work_mutex);
if (wi->free) {
g_free(wi);
} else {
atomic_mb_set(&wi->done, true);
}
}
cpu->queued_work_last = NULL;
qemu_mutex_unlock(&cpu->work_mutex);
qemu_cond_broadcast(&qemu_work_cond);
}
@@ -919,15 +904,13 @@ static void qemu_wait_io_event_common(CPUState *cpu)
cpu->thread_kicked = false;
}
static void qemu_tcg_wait_io_event(void)
static void qemu_tcg_wait_io_event(CPUState *cpu)
{
CPUState *cpu;
while (all_cpu_threads_idle()) {
/* Start accounting real time to the virtual clock if the CPUs
are idle. */
qemu_clock_warp(QEMU_CLOCK_VIRTUAL);
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
}
while (iothread_requesting_mutex) {
@@ -1041,7 +1024,6 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
rcu_register_thread();
qemu_mutex_lock_iothread();
qemu_tcg_init_cpu_signals();
qemu_thread_get_self(cpu->thread);
CPU_FOREACH(cpu) {
@@ -1053,7 +1035,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
/* wait for initial kick-off after machine start */
while (first_cpu->stopped) {
qemu_cond_wait(tcg_halt_cond, &qemu_global_mutex);
qemu_cond_wait(first_cpu->halt_cond, &qemu_global_mutex);
/* process any pending work */
CPU_FOREACH(cpu) {
@@ -1062,7 +1044,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
}
/* process any pending work */
exit_request = 1;
atomic_mb_set(&exit_request, 1);
while (1) {
tcg_exec_all();
@@ -1074,7 +1056,7 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
}
qemu_tcg_wait_io_event();
qemu_tcg_wait_io_event(QTAILQ_FIRST(&cpus));
}
return NULL;
@@ -1085,61 +1067,47 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
#ifndef _WIN32
int err;
if (cpu->thread_kicked) {
return;
}
cpu->thread_kicked = true;
err = pthread_kill(cpu->thread->thread, SIG_IPI);
if (err) {
fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
exit(1);
}
#else /* _WIN32 */
if (!qemu_cpu_is_self(cpu)) {
CONTEXT tcgContext;
if (SuspendThread(cpu->hThread) == (DWORD)-1) {
fprintf(stderr, "qemu:%s: GetLastError:%lu\n", __func__,
GetLastError());
exit(1);
}
/* On multi-core systems, we are not sure that the thread is actually
* suspended until we can get the context.
*/
tcgContext.ContextFlags = CONTEXT_CONTROL;
while (GetThreadContext(cpu->hThread, &tcgContext) != 0) {
continue;
}
cpu_signal(0);
if (ResumeThread(cpu->hThread) == (DWORD)-1) {
fprintf(stderr, "qemu:%s: GetLastError:%lu\n", __func__,
GetLastError());
exit(1);
}
}
abort();
#endif
}
static void qemu_cpu_kick_no_halt(void)
{
CPUState *cpu;
/* Ensure whatever caused the exit has reached the CPU threads before
* writing exit_request.
*/
atomic_mb_set(&exit_request, 1);
cpu = atomic_mb_read(&tcg_current_cpu);
if (cpu) {
cpu_exit(cpu);
}
}
void qemu_cpu_kick(CPUState *cpu)
{
qemu_cond_broadcast(cpu->halt_cond);
if (!tcg_enabled() && !cpu->thread_kicked) {
if (tcg_enabled()) {
qemu_cpu_kick_no_halt();
} else {
qemu_cpu_kick_thread(cpu);
cpu->thread_kicked = true;
}
}
void qemu_cpu_kick_self(void)
{
#ifndef _WIN32
assert(current_cpu);
if (!current_cpu->thread_kicked) {
qemu_cpu_kick_thread(current_cpu);
current_cpu->thread_kicked = true;
}
#else
abort();
#endif
qemu_cpu_kick_thread(current_cpu);
}
bool qemu_cpu_is_self(CPUState *cpu)
@@ -1166,12 +1134,12 @@ void qemu_mutex_lock_iothread(void)
* TCG code execution.
*/
if (!tcg_enabled() || qemu_in_vcpu_thread() ||
!first_cpu || !first_cpu->thread) {
!first_cpu || !first_cpu->created) {
qemu_mutex_lock(&qemu_global_mutex);
atomic_dec(&iothread_requesting_mutex);
} else {
if (qemu_mutex_trylock(&qemu_global_mutex)) {
qemu_cpu_kick_thread(first_cpu);
qemu_cpu_kick_no_halt();
qemu_mutex_lock(&qemu_global_mutex);
}
atomic_dec(&iothread_requesting_mutex);
@@ -1251,6 +1219,8 @@ void resume_all_vcpus(void)
static void qemu_tcg_init_vcpu(CPUState *cpu)
{
char thread_name[VCPU_THREAD_NAME_SIZE];
static QemuCond *tcg_halt_cond;
static QemuThread *tcg_cpu_thread;
tcg_cpu_address_space_init(cpu, cpu->as);
@@ -1440,7 +1410,9 @@ static void tcg_exec_all(void)
break;
}
}
exit_request = 0;
/* Pairs with smp_wmb in qemu_cpu_kick. */
atomic_mb_set(&exit_request, 0);
}
void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
+1 -1
View File
@@ -90,7 +90,7 @@ static MemoryRegion io_mem_unassigned;
struct CPUTailQ cpus = QTAILQ_HEAD_INITIALIZER(cpus);
/* current CPU in the current thread. It is only valid inside
cpu_exec() */
DEFINE_TLS(CPUState *, current_cpu);
__thread CPUState *current_cpu;
/* 0 = Do not count executed instructions.
1 = Precise instruction counting.
2 = Adaptive rate instruction counting. */
+1 -1
View File
@@ -1359,7 +1359,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
is still in the running state, which can cause packets to be dropped
and state transition 'T' packets to be sent while the syscall is still
being processed. */
cpu_exit(s->c_cpu);
qemu_cpu_kick(s->c_cpu);
#endif
}
+1 -1
View File
@@ -1417,7 +1417,7 @@ static void fdctrl_start_transfer(FDCtrl *fdctrl, int direction)
* recall us...
*/
DMA_hold_DREQ(fdctrl->dma_chann);
DMA_schedule(fdctrl->dma_chann);
DMA_schedule();
} else {
/* Start transfer */
fdctrl_transfer_handler(fdctrl, fdctrl->dma_chann, 0,
+1 -4
View File
@@ -38,7 +38,6 @@ do { fprintf(stderr, "i82374 ERROR: " fmt , ## __VA_ARGS__); } while (0)
typedef struct I82374State {
uint8_t commands[8];
qemu_irq out;
PortioList port_list;
} I82374State;
@@ -101,7 +100,7 @@ static uint32_t i82374_read_descriptor(void *opaque, uint32_t nport)
static void i82374_realize(I82374State *s, Error **errp)
{
DMA_init(1, &s->out);
DMA_init(1);
memset(s->commands, 0, sizeof(s->commands));
}
@@ -145,8 +144,6 @@ static void i82374_isa_realize(DeviceState *dev, Error **errp)
isa->iobase);
i82374_realize(s, errp);
qdev_init_gpio_out(dev, &s->out, 1);
}
static Property i82374_properties[] = {
+16 -15
View File
@@ -59,7 +59,6 @@ static struct dma_cont {
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
qemu_irq *cpu_request_exit;
MemoryRegion channel_io;
MemoryRegion cont_io;
} dma_controllers[2];
@@ -358,6 +357,7 @@ static void channel_run (int ncont, int ichan)
}
static QEMUBH *dma_bh;
static bool dma_bh_scheduled;
static void DMA_run (void)
{
@@ -390,12 +390,15 @@ static void DMA_run (void)
running = 0;
out:
if (rearm)
if (rearm) {
qemu_bh_schedule_idle(dma_bh);
dma_bh_scheduled = true;
}
}
static void DMA_run_bh(void *unused)
{
dma_bh_scheduled = false;
DMA_run();
}
@@ -458,12 +461,14 @@ int DMA_write_memory (int nchan, void *buf, int pos, int len)
return len;
}
/* request the emulator to transfer a new DMA memory block ASAP */
void DMA_schedule(int nchan)
/* request the emulator to transfer a new DMA memory block ASAP (even
* if the idle bottom half would not have exited the iothread yet).
*/
void DMA_schedule(void)
{
struct dma_cont *d = &dma_controllers[nchan > 3];
qemu_irq_pulse(*d->cpu_request_exit);
if (dma_bh_scheduled) {
qemu_notify_event();
}
}
static void dma_reset(void *opaque)
@@ -515,13 +520,11 @@ static const MemoryRegionOps cont_io_ops = {
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
int page_base, int pageh_base,
qemu_irq *cpu_request_exit)
int page_base, int pageh_base)
{
int i;
d->dshift = dshift;
d->cpu_request_exit = cpu_request_exit;
memory_region_init_io(&d->channel_io, NULL, &channel_io_ops, d,
"dma-chan", 8 << d->dshift);
@@ -585,12 +588,10 @@ static const VMStateDescription vmstate_dma = {
}
};
void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
void DMA_init(int high_page_enable)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
high_page_enable ? 0x480 : -1, cpu_request_exit);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
high_page_enable ? 0x488 : -1, cpu_request_exit);
dma_init2(&dma_controllers[0], 0x00, 0, 0x80, high_page_enable ? 0x480 : -1);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88, high_page_enable ? 0x488 : -1);
vmstate_register (NULL, 0, &vmstate_dma, &dma_controllers[0]);
vmstate_register (NULL, 1, &vmstate_dma, &dma_controllers[1]);
+1 -12
View File
@@ -1452,15 +1452,6 @@ DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus)
return dev;
}
static void cpu_request_exit(void *opaque, int irq, int level)
{
CPUState *cpu = current_cpu;
if (cpu && level) {
cpu_exit(cpu);
}
}
static const MemoryRegionOps ioport80_io_ops = {
.write = ioport80_write,
.read = ioport80_read,
@@ -1495,7 +1486,6 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042, *port92, *vmmouse, *pit = NULL;
qemu_irq *cpu_exit_irq;
MemoryRegion *ioport80_io = g_new(MemoryRegion, 1);
MemoryRegion *ioportF0_io = g_new(MemoryRegion, 1);
@@ -1572,8 +1562,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
port92 = isa_create_simple(isa_bus, "port92");
port92_init(port92, &a20_line[1]);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
DMA_init(0);
for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i);
+1 -2
View File
@@ -100,7 +100,6 @@ static void i82378_realize(PCIDevice *pci, Error **errp)
/* 2 82C37 (dma) */
isa = isa_create_simple(isabus, "i82374");
qdev_connect_gpio_out(DEVICE(isa), 0, s->out[1]);
/* timer */
isa_create_simple(isabus, "mc146818rtc");
@@ -111,7 +110,7 @@ static void i82378_init(Object *obj)
DeviceState *dev = DEVICE(obj);
I82378State *s = I82378(obj);
qdev_init_gpio_out(dev, s->out, 2);
qdev_init_gpio_out(dev, s->out, 1);
qdev_init_gpio_in(dev, i82378_request_pic_irq, 16);
}
+1 -12
View File
@@ -251,15 +251,6 @@ static void network_init (PCIBus *pci_bus)
}
}
static void cpu_request_exit(void *opaque, int irq, int level)
{
CPUState *cpu = current_cpu;
if (cpu && level) {
cpu_exit(cpu);
}
}
static void mips_fulong2e_init(MachineState *machine)
{
ram_addr_t ram_size = machine->ram_size;
@@ -274,7 +265,6 @@ static void mips_fulong2e_init(MachineState *machine)
long bios_size;
int64_t kernel_entry;
qemu_irq *i8259;
qemu_irq *cpu_exit_irq;
PCIBus *pci_bus;
ISABus *isa_bus;
I2CBus *smbus;
@@ -375,8 +365,7 @@ static void mips_fulong2e_init(MachineState *machine)
/* init other devices */
pit = pit_init(isa_bus, 0x40, 0, NULL);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
DMA_init(0);
/* Super I/O */
isa_create_simple(isa_bus, "i8042");
+1 -12
View File
@@ -104,15 +104,6 @@ static const MemoryRegionOps dma_dummy_ops = {
#define MAGNUM_BIOS_SIZE_MAX 0x7e000
#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
static void cpu_request_exit(void *opaque, int irq, int level)
{
CPUState *cpu = current_cpu;
if (cpu && level) {
cpu_exit(cpu);
}
}
static CPUUnassignedAccess real_do_unassigned_access;
static void mips_jazz_do_unassigned_access(CPUState *cpu, hwaddr addr,
bool is_write, bool is_exec,
@@ -150,7 +141,6 @@ static void mips_jazz_init(MachineState *machine,
ISADevice *pit;
DriveInfo *fds[MAX_FD];
qemu_irq esp_reset, dma_enable;
qemu_irq *cpu_exit_irq;
MemoryRegion *ram = g_new(MemoryRegion, 1);
MemoryRegion *bios = g_new(MemoryRegion, 1);
MemoryRegion *bios2 = g_new(MemoryRegion, 1);
@@ -234,8 +224,7 @@ static void mips_jazz_init(MachineState *machine,
/* ISA devices */
i8259 = i8259_init(isa_bus, env->irq[4]);
isa_bus_irqs(isa_bus, i8259);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
DMA_init(0);
pit = pit_init(isa_bus, 0x40, 0, NULL);
pcspk_init(isa_bus, pit);
+1 -12
View File
@@ -905,15 +905,6 @@ static void main_cpu_reset(void *opaque)
}
}
static void cpu_request_exit(void *opaque, int irq, int level)
{
CPUState *cpu = current_cpu;
if (cpu && level) {
cpu_exit(cpu);
}
}
static
void mips_malta_init(MachineState *machine)
{
@@ -939,7 +930,6 @@ void mips_malta_init(MachineState *machine)
MIPSCPU *cpu;
CPUMIPSState *env;
qemu_irq *isa_irq;
qemu_irq *cpu_exit_irq;
int piix4_devfn;
I2CBus *smbus;
int i;
@@ -1175,8 +1165,7 @@ void mips_malta_init(MachineState *machine)
smbus_eeprom_init(smbus, 8, smbus_eeprom_buf, smbus_eeprom_size);
g_free(smbus_eeprom_buf);
pit = pit_init(isa_bus, 0x40, 0, NULL);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);
DMA_init(0);
/* Super I/O */
isa_create_simple(isa_bus, "i8042");
+1 -2
View File
@@ -41,8 +41,7 @@ static void handle_event(int event)
}
if (event & PVPANIC_PANICKED) {
qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_PAUSE, &error_abort);
vm_stop(RUN_STATE_GUEST_PANICKED);
qemu_system_guest_panicked();
return;
}
}
-11
View File
@@ -336,15 +336,6 @@ static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
#define NVRAM_SIZE 0x2000
static void cpu_request_exit(void *opaque, int irq, int level)
{
CPUState *cpu = current_cpu;
if (cpu && level) {
cpu_exit(cpu);
}
}
static void ppc_prep_reset(void *opaque)
{
PowerPCCPU *cpu = opaque;
@@ -626,8 +617,6 @@ static void ppc_prep_init(MachineState *machine)
cpu = POWERPC_CPU(first_cpu);
qdev_connect_gpio_out(&pci->qdev, 0,
cpu->env.irq_inputs[PPC6xx_INPUT_INT]);
qdev_connect_gpio_out(&pci->qdev, 1,
qemu_allocate_irq(cpu_request_exit, NULL, 0));
sysbus_connect_irq(&pcihost->busdev, 0, qdev_get_gpio_in(&pci->qdev, 9));
sysbus_connect_irq(&pcihost->busdev, 1, qdev_get_gpio_in(&pci->qdev, 11));
sysbus_connect_irq(&pcihost->busdev, 2, qdev_get_gpio_in(&pci->qdev, 9));
+1 -1
View File
@@ -214,7 +214,7 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
CPUPPCState *env = &cpu->env;
cs->halted = 1;
cpu_exit(cs);
qemu_cpu_kick(cs);
/*
* While stopping a CPU, the guest calls H_CPPR which
* effectively disables interrupts on XICS level.

Some files were not shown because too many files have changed in this diff Show More