Generic CPUs / accelerators patch queue
- Access CPUState::thread_kicked atomically - Fix bql_locked status with condvar APIs - Document cpu_memory_rw_debug() - Rename init_clocks() -> qemu_init_clocks() to avoid name clashing - Fix QEMU_HEXDUMP_LINE_WIDTH logic - Fix interrupts check in rx_cpu_do_interrupt() -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmkIrCIACgkQ4+MsLN6t wN6wSRAAkfYKbLKLqdrYpuz+D94KSnhrBxqXaC9RH+Q48VQS5Du4IBXfuTPtUa5+ ii73XmEl3J83NbK+miH5rqRuRNCqj/MC1MUeFuXDjI2kkIupZMnarus4kS/zZ0zE KgJeZxfuHXkxs7SLjk/N1b8/BJSZXfXybtNVhnzPTS6UyuGvx3MBf5g3NtwlVC4B J3o/5klyxFzB9oyASg0pTCXnjdTnqakre1MnYFoEctxDq+W3AJgiT6MVkVWuPtxn AbN1Zf9vi/e7UyVB2r8NprMfgukJBiMIQK/yfwkWOr1iE4aUSapLCvZEc1ZuL5RF asFZ5sptn0QU0nJX2UTs/dWWdukLyffem/OIp737WsXR3EPCcWIEVF8oXlRcdGR0 BBkyWP6H0v75lvD4V+cn0hUXeT2tSAWBddtSvIZ08tfIo1z6s+ckVPY1C3m3xbXt BsWjKaFG7UlkUXfmgXlkaNYzzicZTg1arOIQ4InPlIeJ+6gzWad3ciRk7zIyEpSA EizIIxI9WILcG2Qp5MvXuCiTQvPlN2AhOq7Z3L+XyeAK/7qXpUmlrdMeTshJE5z4 rQHt0tb689ma/Vm0/NbZZ8RY66xgdpGcYjNYgthm4nkah02a07keLVKXxBF8oWbV v4LRE9Vprv0WP8zVKfuWi7s/L2HmNZodHGB+lrAJddqTl7X2lIc= =BKNk -----END PGP SIGNATURE----- Merge tag 'accel-cpus-20251103' of https://github.com/philmd/qemu into staging Generic CPUs / accelerators patch queue - Access CPUState::thread_kicked atomically - Fix bql_locked status with condvar APIs - Document cpu_memory_rw_debug() - Rename init_clocks() -> qemu_init_clocks() to avoid name clashing - Fix QEMU_HEXDUMP_LINE_WIDTH logic - Fix interrupts check in rx_cpu_do_interrupt() # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEE+qvnXhKRciHc/Wuy4+MsLN6twN4FAmkIrCIACgkQ4+MsLN6t # wN6wSRAAkfYKbLKLqdrYpuz+D94KSnhrBxqXaC9RH+Q48VQS5Du4IBXfuTPtUa5+ # ii73XmEl3J83NbK+miH5rqRuRNCqj/MC1MUeFuXDjI2kkIupZMnarus4kS/zZ0zE # KgJeZxfuHXkxs7SLjk/N1b8/BJSZXfXybtNVhnzPTS6UyuGvx3MBf5g3NtwlVC4B # J3o/5klyxFzB9oyASg0pTCXnjdTnqakre1MnYFoEctxDq+W3AJgiT6MVkVWuPtxn # AbN1Zf9vi/e7UyVB2r8NprMfgukJBiMIQK/yfwkWOr1iE4aUSapLCvZEc1ZuL5RF # asFZ5sptn0QU0nJX2UTs/dWWdukLyffem/OIp737WsXR3EPCcWIEVF8oXlRcdGR0 # BBkyWP6H0v75lvD4V+cn0hUXeT2tSAWBddtSvIZ08tfIo1z6s+ckVPY1C3m3xbXt # BsWjKaFG7UlkUXfmgXlkaNYzzicZTg1arOIQ4InPlIeJ+6gzWad3ciRk7zIyEpSA # EizIIxI9WILcG2Qp5MvXuCiTQvPlN2AhOq7Z3L+XyeAK/7qXpUmlrdMeTshJE5z4 # rQHt0tb689ma/Vm0/NbZZ8RY66xgdpGcYjNYgthm4nkah02a07keLVKXxBF8oWbV # v4LRE9Vprv0WP8zVKfuWi7s/L2HmNZodHGB+lrAJddqTl7X2lIc= # =BKNk # -----END PGP SIGNATURE----- # gpg: Signature made Mon 03 Nov 2025 02:20:34 PM CET # gpg: using RSA key FAABE75E12917221DCFD6BB2E3E32C2CDEADC0DE # gpg: Good signature from "Philippe Mathieu-Daudé (F4BUG) <f4bug@amsat.org>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: FAAB E75E 1291 7221 DCFD 6BB2 E3E3 2C2C DEAD C0DE * tag 'accel-cpus-20251103' of https://github.com/philmd/qemu: rx: cpu: fix interrupts check in rx_cpu_do_interrupt() util/hexdump: fix QEMU_HEXDUMP_LINE_WIDTH logic timers: properly prefix init_clocks() exec/cpu: Declare cpu_memory_rw_debug() in 'hw/core/cpu.h' and document bql: Fix bql_locked status with condvar APIs accel/tcg: Use cpu_is_stopped() helper to access CPUState::stopped cpus: Access CPUState::thread_kicked atomically Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
dcc6d1d956
13 changed files with 119 additions and 53 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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++) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue