Devices can pass their MemoryReentrancyGuard (from their DeviceState), when creating new BHes. Then, the async API will toggle the guard before/after calling the BH call-back. This prevents bh->mmio reentrancy issues. Signed-off-by: Alexander Bulekov <alxndr@bu.edu> Reviewed-by: Darren Kenny <darren.kenny@oracle.com> Message-Id: <20230427211013.2994127-3-alxndr@bu.edu> [thuth: Fix "line over 90 characters" checkpatch.pl error] Signed-off-by: Thomas Huth <thuth@redhat.com>
		
			
				
	
	
		
			125 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			125 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Stubs for the ptimer-test
 | 
						|
 *
 | 
						|
 * Copyright (c) 2016 Dmitry Osipenko <digetx@gmail.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.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#include "qemu/osdep.h"
 | 
						|
#include "qemu/main-loop.h"
 | 
						|
#include "exec/replay-core.h"
 | 
						|
#include "migration/vmstate.h"
 | 
						|
 | 
						|
#include "ptimer-test.h"
 | 
						|
 | 
						|
const VMStateInfo vmstate_info_uint8;
 | 
						|
const VMStateInfo vmstate_info_uint32;
 | 
						|
const VMStateInfo vmstate_info_uint64;
 | 
						|
const VMStateInfo vmstate_info_int64;
 | 
						|
const VMStateInfo vmstate_info_timer;
 | 
						|
 | 
						|
struct QEMUBH {
 | 
						|
    QEMUBHFunc *cb;
 | 
						|
    void *opaque;
 | 
						|
};
 | 
						|
 | 
						|
QEMUTimerListGroup main_loop_tlg;
 | 
						|
 | 
						|
int64_t ptimer_test_time_ns;
 | 
						|
 | 
						|
/* under qtest_enabled(), will not artificially limit period - see hw/core/ptimer.c. */
 | 
						|
int use_icount;
 | 
						|
bool qtest_allowed;
 | 
						|
 | 
						|
void timer_init_full(QEMUTimer *ts,
 | 
						|
                     QEMUTimerListGroup *timer_list_group, QEMUClockType type,
 | 
						|
                     int scale, int attributes,
 | 
						|
                     QEMUTimerCB *cb, void *opaque)
 | 
						|
{
 | 
						|
    if (!timer_list_group) {
 | 
						|
        timer_list_group = &main_loop_tlg;
 | 
						|
    }
 | 
						|
    ts->timer_list = timer_list_group->tl[type];
 | 
						|
    ts->cb = cb;
 | 
						|
    ts->opaque = opaque;
 | 
						|
    ts->scale = scale;
 | 
						|
    ts->attributes = attributes;
 | 
						|
    ts->expire_time = -1;
 | 
						|
}
 | 
						|
 | 
						|
void timer_mod(QEMUTimer *ts, int64_t expire_time)
 | 
						|
{
 | 
						|
    QEMUTimerList *timer_list = ts->timer_list;
 | 
						|
    QEMUTimer *t = &timer_list->active_timers;
 | 
						|
 | 
						|
    while (t->next != NULL) {
 | 
						|
        if (t->next == ts) {
 | 
						|
            break;
 | 
						|
        }
 | 
						|
 | 
						|
        t = t->next;
 | 
						|
    }
 | 
						|
 | 
						|
    ts->expire_time = MAX(expire_time * ts->scale, 0);
 | 
						|
    ts->next = NULL;
 | 
						|
    t->next = ts;
 | 
						|
}
 | 
						|
 | 
						|
void timer_del(QEMUTimer *ts)
 | 
						|
{
 | 
						|
    QEMUTimerList *timer_list = ts->timer_list;
 | 
						|
    QEMUTimer *t = &timer_list->active_timers;
 | 
						|
 | 
						|
    while (t->next != NULL) {
 | 
						|
        if (t->next == ts) {
 | 
						|
            t->next = ts->next;
 | 
						|
            return;
 | 
						|
        }
 | 
						|
 | 
						|
        t = t->next;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int64_t qemu_clock_get_ns(QEMUClockType type)
 | 
						|
{
 | 
						|
    return ptimer_test_time_ns;
 | 
						|
}
 | 
						|
 | 
						|
int64_t qemu_clock_deadline_ns_all(QEMUClockType type, int attr_mask)
 | 
						|
{
 | 
						|
    QEMUTimerList *timer_list = main_loop_tlg.tl[QEMU_CLOCK_VIRTUAL];
 | 
						|
    QEMUTimer *t = timer_list->active_timers.next;
 | 
						|
    int64_t deadline = -1;
 | 
						|
 | 
						|
    while (t != NULL) {
 | 
						|
        if (deadline == -1) {
 | 
						|
            deadline = t->expire_time;
 | 
						|
        } else {
 | 
						|
            deadline = MIN(deadline, t->expire_time);
 | 
						|
        }
 | 
						|
 | 
						|
        t = t->next;
 | 
						|
    }
 | 
						|
 | 
						|
    return deadline;
 | 
						|
}
 | 
						|
 | 
						|
QEMUBH *qemu_bh_new_full(QEMUBHFunc *cb, void *opaque, const char *name,
 | 
						|
                         MemReentrancyGuard *reentrancy_guard)
 | 
						|
{
 | 
						|
    QEMUBH *bh = g_new(QEMUBH, 1);
 | 
						|
 | 
						|
    bh->cb = cb;
 | 
						|
    bh->opaque = opaque;
 | 
						|
 | 
						|
    return bh;
 | 
						|
}
 | 
						|
 | 
						|
void qemu_bh_delete(QEMUBH *bh)
 | 
						|
{
 | 
						|
    g_free(bh);
 | 
						|
}
 |