diff --git a/accel/tcg/tcg-accel-ops-rr.c b/accel/tcg/tcg-accel-ops-rr.c index 2fb4643997..f84342e044 100644 --- a/accel/tcg/tcg-accel-ops-rr.c +++ b/accel/tcg/tcg-accel-ops-rr.c @@ -197,7 +197,7 @@ static void *rr_cpu_thread_fn(void *arg) qemu_guest_random_seed_thread_part2(cpu->random_seed); /* wait for initial kick-off after machine start */ - while (first_cpu->stopped) { + while (cpu_is_stopped(first_cpu)) { qemu_cond_wait_bql(first_cpu->halt_cond); /* process any pending work */ diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 67e15c8e50..e0be4ee2b8 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -150,10 +150,6 @@ typedef int (RAMBlockIterFunc)(RAMBlock *rb, void *opaque); int qemu_ram_foreach_block(RAMBlockIterFunc func, void *opaque); -/* Returns: 0 on success, -1 on error */ -int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, - void *ptr, size_t len, bool is_write); - /* vl.c */ void list_cpus(void); diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index e79e8e0a8e..9615051774 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -688,6 +688,26 @@ int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu, int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu, void *opaque); +/** + * cpu_memory_rw_debug: + * @cpu: The CPU whose memory is to be accessed + * @addr: guest virtual address + * @ptr: buffer with the data transferred + * @len: the number of bytes to read or write + * @is_write: indicates the transfer direction + * + * Take a virtual address, convert it to a physical address via + * an MMU lookup using the current settings of the specified CPU, + * and then perform the access (using address_space_rw() for + * reads or address_space_write_rom() for writes). + * + * This function is intended for use by the GDB stub and similar code. + * + * Returns: 0 on success, -1 on error + */ +int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, + void *ptr, size_t len, bool is_write); + /** * cpu_get_crash_info: * @cpu: The CPU to get crash information for diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index 4e2436b196..0d55c636b2 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -270,6 +270,24 @@ void rust_bql_mock_lock(void); */ bool bql_locked(void); +/** + * mutex_is_bql: + * + * @mutex: the mutex pointer + * + * Returns whether the mutex is the BQL. + */ +bool mutex_is_bql(QemuMutex *mutex); + +/** + * bql_update_status: + * + * @locked: update status on whether the BQL is locked + * + * NOTE: this should normally only be invoked when the status changed. + */ +void bql_update_status(bool locked); + /** * bql_block: Allow/deny releasing the BQL * diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 406d741120..8b561cd696 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -786,11 +786,12 @@ static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2) } /** - * initclocks: + * qemu_init_clocks: + * @notify_cb: optional call-back for timer expiry * * Initialise the clock & timer infrastructure */ -void init_clocks(QEMUTimerListNotifyCB *notify_cb); +void qemu_init_clocks(QEMUTimerListNotifyCB *notify_cb); static inline int64_t get_max_clock_jump(void) { diff --git a/stubs/iothread-lock.c b/stubs/iothread-lock.c index 6050c081f5..c89c9c7228 100644 --- a/stubs/iothread-lock.c +++ b/stubs/iothread-lock.c @@ -34,3 +34,12 @@ void bql_block_unlock(bool increase) assert((new_value > bql_unlock_blocked) == increase); bql_unlock_blocked = new_value; } + +bool mutex_is_bql(QemuMutex *mutex) +{ + return false; +} + +void bql_update_status(bool locked) +{ +} diff --git a/system/cpus.c b/system/cpus.c index aa7bfcf56e..ef2d2f241f 100644 --- a/system/cpus.c +++ b/system/cpus.c @@ -480,10 +480,10 @@ void qemu_process_cpu_events(CPUState *cpu) void cpus_kick_thread(CPUState *cpu) { - if (cpu->thread_kicked) { + if (qatomic_read(&cpu->thread_kicked)) { return; } - cpu->thread_kicked = true; + qatomic_set(&cpu->thread_kicked, true); #ifndef _WIN32 int err = pthread_kill(cpu->thread->thread, SIG_IPI); @@ -524,6 +524,18 @@ bool qemu_in_vcpu_thread(void) QEMU_DEFINE_STATIC_CO_TLS(bool, bql_locked) +bool mutex_is_bql(QemuMutex *mutex) +{ + return mutex == &bql; +} + +void bql_update_status(bool locked) +{ + /* This function should only be used when an update happened.. */ + assert(bql_locked() != locked); + set_bql_locked(locked); +} + static uint32_t bql_unlock_blocked; void bql_block_unlock(bool increase) @@ -564,14 +576,12 @@ void bql_lock_impl(const char *file, int line) g_assert(!bql_locked()); bql_lock_fn(&bql, file, line); - set_bql_locked(true); } void bql_unlock(void) { g_assert(bql_locked()); g_assert(!bql_unlock_blocked); - set_bql_locked(false); qemu_mutex_unlock(&bql); } diff --git a/target/rx/helper.c b/target/rx/helper.c index ef47e32add..e9a7aaf610 100644 --- a/target/rx/helper.c +++ b/target/rx/helper.c @@ -41,11 +41,9 @@ void rx_cpu_unpack_psw(CPURXState *env, uint32_t psw, int rte) env->psw_c = FIELD_EX32(psw, PSW, C); } -#define INT_FLAGS (CPU_INTERRUPT_HARD | CPU_INTERRUPT_FIR) void rx_cpu_do_interrupt(CPUState *cs) { CPURXState *env = cpu_env(cs); - int do_irq = cpu_test_interrupt(cs, INT_FLAGS); uint32_t save_psw; uint64_t last_pc = env->pc; @@ -59,29 +57,26 @@ void rx_cpu_do_interrupt(CPUState *cs) save_psw = rx_cpu_pack_psw(env); env->psw_pm = env->psw_i = env->psw_u = 0; - if (do_irq) { - if (do_irq & CPU_INTERRUPT_FIR) { - env->bpc = env->pc; - env->bpsw = save_psw; - env->pc = env->fintv; - env->psw_ipl = 15; - cpu_reset_interrupt(cs, CPU_INTERRUPT_FIR); - qemu_set_irq(env->ack, env->ack_irq); - qemu_plugin_vcpu_interrupt_cb(cs, last_pc); - qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n"); - } else if (do_irq & CPU_INTERRUPT_HARD) { - env->isp -= 4; - cpu_stl_data(env, env->isp, save_psw); - env->isp -= 4; - cpu_stl_data(env, env->isp, env->pc); - env->pc = cpu_ldl_data(env, env->intb + env->ack_irq * 4); - env->psw_ipl = env->ack_ipl; - cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); - qemu_set_irq(env->ack, env->ack_irq); - qemu_plugin_vcpu_interrupt_cb(cs, last_pc); - qemu_log_mask(CPU_LOG_INT, - "interrupt 0x%02x raised\n", env->ack_irq); - } + if (cpu_test_interrupt(cs, CPU_INTERRUPT_FIR)) { + env->bpc = env->pc; + env->bpsw = save_psw; + env->pc = env->fintv; + env->psw_ipl = 15; + cpu_reset_interrupt(cs, CPU_INTERRUPT_FIR); + qemu_set_irq(env->ack, env->ack_irq); + qemu_plugin_vcpu_interrupt_cb(cs, last_pc); + qemu_log_mask(CPU_LOG_INT, "fast interrupt raised\n"); + } else if (cpu_test_interrupt(cs, CPU_INTERRUPT_HARD)) { + env->isp -= 4; + cpu_stl_data(env, env->isp, save_psw); + env->isp -= 4; + cpu_stl_data(env, env->isp, env->pc); + env->pc = cpu_ldl_data(env, env->intb + env->ack_irq * 4); + env->psw_ipl = env->ack_ipl; + cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD); + qemu_set_irq(env->ack, env->ack_irq); + qemu_plugin_vcpu_interrupt_cb(cs, last_pc); + qemu_log_mask(CPU_LOG_INT, "interrupt 0x%02x raised\n", env->ack_irq); } else { uint32_t vec = cs->exception_index; const char *expname = "unknown exception"; diff --git a/tests/unit/test-aio-multithread.c b/tests/unit/test-aio-multithread.c index 0ead6bf34a..c24200a712 100644 --- a/tests/unit/test-aio-multithread.c +++ b/tests/unit/test-aio-multithread.c @@ -443,7 +443,7 @@ static void test_multi_mutex_10(void) int main(int argc, char **argv) { - init_clocks(NULL); + qemu_init_clocks(NULL); g_test_init(&argc, &argv, NULL); g_test_add_func("/aio/multi/lifecycle", test_lifecycle); diff --git a/util/hexdump.c b/util/hexdump.c index f29ffceb74..7cfc547261 100644 --- a/util/hexdump.c +++ b/util/hexdump.c @@ -22,6 +22,19 @@ static inline char hexdump_nibble(unsigned x) return (x < 10 ? '0' : 'a' - 10) + x; } +static size_t hexdump_line_length(size_t buf_len, size_t unit_len, + size_t block_len) +{ + size_t est = buf_len * 2; + if (unit_len) { + est += buf_len / unit_len; + } + if (block_len) { + est += buf_len / block_len; + } + return est; +} + GString *qemu_hexdump_line(GString *str, const void *vbuf, size_t len, size_t unit_len, size_t block_len) { @@ -30,14 +43,8 @@ GString *qemu_hexdump_line(GString *str, const void *vbuf, size_t len, if (str == NULL) { /* Estimate the length of the output to avoid reallocs. */ - size_t est = len * 2; - if (unit_len) { - est += len / unit_len; - } - if (block_len) { - est += len / block_len; - } - str = g_string_sized_new(est + 1); + str = g_string_sized_new(hexdump_line_length(len, unit_len, block_len) + + 1); } for (u = 0, b = 0; len; u++, b++, len--, buf++) { @@ -76,13 +83,16 @@ static void asciidump_line(char *line, const void *bufptr, size_t len) } #define QEMU_HEXDUMP_LINE_BYTES 16 -#define QEMU_HEXDUMP_LINE_WIDTH \ - (QEMU_HEXDUMP_LINE_BYTES * 2 + QEMU_HEXDUMP_LINE_BYTES / 4) +#define QEMU_HEXDUMP_UNIT 1 +#define QEMU_HEXDUMP_BLOCK 4 void qemu_hexdump(FILE *fp, const char *prefix, const void *bufptr, size_t size) { - g_autoptr(GString) str = g_string_sized_new(QEMU_HEXDUMP_LINE_WIDTH + 1); + int width = hexdump_line_length(QEMU_HEXDUMP_LINE_BYTES, + QEMU_HEXDUMP_UNIT, + QEMU_HEXDUMP_BLOCK); + g_autoptr(GString) str = g_string_sized_new(width + 1); char ascii[QEMU_HEXDUMP_LINE_BYTES + 1]; size_t b, len; @@ -90,11 +100,11 @@ void qemu_hexdump(FILE *fp, const char *prefix, len = MIN(size - b, QEMU_HEXDUMP_LINE_BYTES); g_string_truncate(str, 0); - qemu_hexdump_line(str, bufptr + b, len, 1, 4); + qemu_hexdump_line(str, bufptr + b, len, + QEMU_HEXDUMP_UNIT, QEMU_HEXDUMP_BLOCK); asciidump_line(ascii, bufptr + b, len); - fprintf(fp, "%s: %04zx: %-*s %s\n", - prefix, b, QEMU_HEXDUMP_LINE_WIDTH, str->str, ascii); + fprintf(fp, "%s: %04zx: %-*s %s\n", prefix, b, width, str->str, ascii); } } diff --git a/util/main-loop.c b/util/main-loop.c index b8ddda8f5e..b462598f76 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -162,7 +162,7 @@ int qemu_init_main_loop(Error **errp) int ret; GSource *src; - init_clocks(qemu_timer_notify_cb); + qemu_init_clocks(qemu_timer_notify_cb); ret = qemu_signal_init(errp); if (ret) { diff --git a/util/qemu-thread-common.h b/util/qemu-thread-common.h index 2af6b12085..09331843ba 100644 --- a/util/qemu-thread-common.h +++ b/util/qemu-thread-common.h @@ -14,6 +14,7 @@ #define QEMU_THREAD_COMMON_H #include "qemu/thread.h" +#include "qemu/main-loop.h" #include "trace.h" static inline void qemu_mutex_post_init(QemuMutex *mutex) @@ -39,6 +40,9 @@ static inline void qemu_mutex_post_lock(QemuMutex *mutex, mutex->line = line; #endif trace_qemu_mutex_locked(mutex, file, line); + if (mutex_is_bql(mutex)) { + bql_update_status(true); + } } static inline void qemu_mutex_pre_unlock(QemuMutex *mutex, @@ -49,6 +53,9 @@ static inline void qemu_mutex_pre_unlock(QemuMutex *mutex, mutex->line = 0; #endif trace_qemu_mutex_unlock(mutex, file, line); + if (mutex_is_bql(mutex)) { + bql_update_status(false); + } } #endif diff --git a/util/qemu-timer.c b/util/qemu-timer.c index 56f11b6a64..2a6be4c7f9 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -637,7 +637,7 @@ static void qemu_virtual_clock_set_ns(int64_t time) return cpus_set_virtual_clock(time); } -void init_clocks(QEMUTimerListNotifyCB *notify_cb) +void qemu_init_clocks(QEMUTimerListNotifyCB *notify_cb) { QEMUClockType type; for (type = 0; type < QEMU_CLOCK_MAX; type++) {