mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'pull-tcg-20221026' of https://gitlab.com/rth7680/qemu into staging
Revert incorrect cflags initialization. Add direct jumps for tcg/loongarch64. Speed up breakpoint check. Improve assertions for atomic.h. Move restore_state_to_opc to TCGCPUOps. Cleanups to TranslationBlock maintenance. # -----BEGIN PGP SIGNATURE----- # # iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmNYlo4dHHJpY2hhcmQu # aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV9y2wf9EKsCA6VtYI2Qtftf # q/ujYFmUf8AKTb9eVcA0XX71CT1dEnFR7GQyT8B8X13x0pSbOX7tbEWHPreegTFV # tESiejvymi6Q9devAB58GVwNoU/zPIQQGhCPxkVUKDmRztJz22MbGUzd7UKPPgU8 # 2nVMkIpLTMBsKeFLxE/D3ZntmdKsgyI/1Dtkl9TxvlDGsCbMjbNcr8lM+TLaG2oX # GZhFyJHKEVy0cobukvhhb/9rU7AWdG/BnFmZM16JxvHV/YCwJBx3Udhcy9xPePUU # yIjkGsUAq4aB6H9RFuTWh7GmaY5u6gMbTTi2J7hDos0mzauYJtpgEB/H42LpycGE # sOhkLQ== # =DUb8 # -----END PGP SIGNATURE----- # gpg: Signature made Tue 25 Oct 2022 22:08:14 EDT # gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F # gpg: issuer "richard.henderson@linaro.org" # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * tag 'pull-tcg-20221026' of https://gitlab.com/rth7680/qemu: (47 commits) accel/tcg: Remove restore_state_to_opc function target/xtensa: Convert to tcg_ops restore_state_to_opc target/tricore: Convert to tcg_ops restore_state_to_opc target/sparc: Convert to tcg_ops restore_state_to_opc target/sh4: Convert to tcg_ops restore_state_to_opc target/s390x: Convert to tcg_ops restore_state_to_opc target/rx: Convert to tcg_ops restore_state_to_opc target/riscv: Convert to tcg_ops restore_state_to_opc target/ppc: Convert to tcg_ops restore_state_to_opc target/openrisc: Convert to tcg_ops restore_state_to_opc target/nios2: Convert to tcg_ops restore_state_to_opc target/mips: Convert to tcg_ops restore_state_to_opc target/microblaze: Convert to tcg_ops restore_state_to_opc target/m68k: Convert to tcg_ops restore_state_to_opc target/loongarch: Convert to tcg_ops restore_state_to_opc target/i386: Convert to tcg_ops restore_state_to_opc target/hppa: Convert to tcg_ops restore_state_to_opc target/hexagon: Convert to tcg_ops restore_state_to_opc target/cris: Convert to tcg_ops restore_state_to_opc target/avr: Convert to tcg_ops restore_state_to_opc ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
+14
-10
@@ -187,13 +187,14 @@ static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
const struct tb_desc *desc = d;
|
||||
|
||||
if ((TARGET_TB_PCREL || tb_pc(tb) == desc->pc) &&
|
||||
tb->page_addr[0] == desc->page_addr0 &&
|
||||
tb_page_addr0(tb) == desc->page_addr0 &&
|
||||
tb->cs_base == desc->cs_base &&
|
||||
tb->flags == desc->flags &&
|
||||
tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
|
||||
tb_cflags(tb) == desc->cflags) {
|
||||
/* check next page if needed */
|
||||
if (tb->page_addr[1] == -1) {
|
||||
tb_page_addr_t tb_phys_page1 = tb_page_addr1(tb);
|
||||
if (tb_phys_page1 == -1) {
|
||||
return true;
|
||||
} else {
|
||||
tb_page_addr_t phys_page1;
|
||||
@@ -210,7 +211,7 @@ static bool tb_lookup_cmp(const void *p, const void *d)
|
||||
*/
|
||||
virt_page1 = TARGET_PAGE_ALIGN(desc->pc);
|
||||
phys_page1 = get_page_addr_code(desc->env, virt_page1);
|
||||
if (tb->page_addr[1] == phys_page1) {
|
||||
if (tb_phys_page1 == phys_page1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -304,16 +305,12 @@ static void log_cpu_exec(target_ulong pc, CPUState *cpu,
|
||||
}
|
||||
}
|
||||
|
||||
static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
static bool check_for_breakpoints_slow(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
{
|
||||
CPUBreakpoint *bp;
|
||||
bool match_page = false;
|
||||
|
||||
if (likely(QTAILQ_EMPTY(&cpu->breakpoints))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Singlestep overrides breakpoints.
|
||||
* This requirement is visible in the record-replay tests, where
|
||||
@@ -374,6 +371,13 @@ static bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool check_for_breakpoints(CPUState *cpu, target_ulong pc,
|
||||
uint32_t *cflags)
|
||||
{
|
||||
return unlikely(!QTAILQ_EMPTY(&cpu->breakpoints)) &&
|
||||
check_for_breakpoints_slow(cpu, pc, cflags);
|
||||
}
|
||||
|
||||
/**
|
||||
* helper_lookup_tb_ptr: quick check for next tb
|
||||
* @env: current cpu state
|
||||
@@ -1016,7 +1020,7 @@ int cpu_exec(CPUState *cpu)
|
||||
* direct jump to a TB spanning two pages because the mapping
|
||||
* for the second page can change.
|
||||
*/
|
||||
if (tb->page_addr[1] != -1) {
|
||||
if (tb_page_addr1(tb) != -1) {
|
||||
last_tb = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -11,12 +11,103 @@
|
||||
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
/*
|
||||
* Access to the various translations structures need to be serialised
|
||||
* via locks for consistency. In user-mode emulation access to the
|
||||
* memory related structures are protected with mmap_lock.
|
||||
* In !user-mode we use per-page locks.
|
||||
*/
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
#define assert_memory_lock()
|
||||
#else
|
||||
#define assert_memory_lock() tcg_debug_assert(have_mmap_lock())
|
||||
#endif
|
||||
|
||||
typedef struct PageDesc {
|
||||
/* list of TBs intersecting this ram page */
|
||||
uintptr_t first_tb;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
unsigned long flags;
|
||||
void *target_data;
|
||||
#endif
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
QemuSpin lock;
|
||||
#endif
|
||||
} PageDesc;
|
||||
|
||||
/* Size of the L2 (and L3, etc) page tables. */
|
||||
#define V_L2_BITS 10
|
||||
#define V_L2_SIZE (1 << V_L2_BITS)
|
||||
|
||||
/*
|
||||
* L1 Mapping properties
|
||||
*/
|
||||
extern int v_l1_size;
|
||||
extern int v_l1_shift;
|
||||
extern int v_l2_levels;
|
||||
|
||||
/*
|
||||
* The bottom level has pointers to PageDesc, and is indexed by
|
||||
* anything from 4 to (V_L2_BITS + 3) bits, depending on target page size.
|
||||
*/
|
||||
#define V_L1_MIN_BITS 4
|
||||
#define V_L1_MAX_BITS (V_L2_BITS + 3)
|
||||
#define V_L1_MAX_SIZE (1 << V_L1_MAX_BITS)
|
||||
|
||||
extern void *l1_map[V_L1_MAX_SIZE];
|
||||
|
||||
PageDesc *page_find_alloc(tb_page_addr_t index, bool alloc);
|
||||
|
||||
static inline PageDesc *page_find(tb_page_addr_t index)
|
||||
{
|
||||
return page_find_alloc(index, false);
|
||||
}
|
||||
|
||||
/* list iterators for lists of tagged pointers in TranslationBlock */
|
||||
#define TB_FOR_EACH_TAGGED(head, tb, n, field) \
|
||||
for (n = (head) & 1, tb = (TranslationBlock *)((head) & ~1); \
|
||||
tb; tb = (TranslationBlock *)tb->field[n], n = (uintptr_t)tb & 1, \
|
||||
tb = (TranslationBlock *)((uintptr_t)tb & ~1))
|
||||
|
||||
#define PAGE_FOR_EACH_TB(pagedesc, tb, n) \
|
||||
TB_FOR_EACH_TAGGED((pagedesc)->first_tb, tb, n, page_next)
|
||||
|
||||
#define TB_FOR_EACH_JMP(head_tb, tb, n) \
|
||||
TB_FOR_EACH_TAGGED((head_tb)->jmp_list_head, tb, n, jmp_list_next)
|
||||
|
||||
/* In user-mode page locks aren't used; mmap_lock is enough */
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#define assert_page_locked(pd) tcg_debug_assert(have_mmap_lock())
|
||||
static inline void page_lock(PageDesc *pd) { }
|
||||
static inline void page_unlock(PageDesc *pd) { }
|
||||
#else
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
void do_assert_page_locked(const PageDesc *pd, const char *file, int line);
|
||||
#define assert_page_locked(pd) do_assert_page_locked(pd, __FILE__, __LINE__)
|
||||
#else
|
||||
#define assert_page_locked(pd)
|
||||
#endif
|
||||
void page_lock(PageDesc *pd);
|
||||
void page_unlock(PageDesc *pd);
|
||||
#endif
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
|
||||
void assert_no_pages_locked(void);
|
||||
#else
|
||||
static inline void assert_no_pages_locked(void) { }
|
||||
#endif
|
||||
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
int cflags);
|
||||
G_NORETURN void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
void page_init(void);
|
||||
void tb_htable_init(void);
|
||||
void tb_reset_jump(TranslationBlock *tb, int n);
|
||||
TranslationBlock *tb_link_page(TranslationBlock *tb, tb_page_addr_t phys_pc,
|
||||
tb_page_addr_t phys_page2);
|
||||
bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc);
|
||||
int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
|
||||
uintptr_t searched_pc, bool reset_icount);
|
||||
|
||||
/* Return the current PC from CPU, which may be cached in TB. */
|
||||
static inline target_ulong log_pc(CPUState *cpu, const TranslationBlock *tb)
|
||||
|
||||
@@ -3,6 +3,7 @@ tcg_ss.add(files(
|
||||
'tcg-all.c',
|
||||
'cpu-exec-common.c',
|
||||
'cpu-exec.c',
|
||||
'tb-maint.c',
|
||||
'tcg-runtime-gvec.c',
|
||||
'tcg-runtime.c',
|
||||
'translate-all.c',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -70,8 +70,6 @@ static void *mttcg_cpu_thread_fn(void *arg)
|
||||
assert(tcg_enabled());
|
||||
g_assert(!icount_enabled());
|
||||
|
||||
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
|
||||
|
||||
rcu_register_thread();
|
||||
force_rcu.notifier.notify = mttcg_force_rcu;
|
||||
force_rcu.cpu = cpu;
|
||||
@@ -141,6 +139,9 @@ void mttcg_start_vcpu_thread(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
g_assert(tcg_enabled());
|
||||
tcg_cpu_init_cflags(cpu, current_machine->smp.max_cpus > 1);
|
||||
|
||||
cpu->thread = g_new0(QemuThread, 1);
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
@@ -152,9 +152,7 @@ static void *rr_cpu_thread_fn(void *arg)
|
||||
Notifier force_rcu;
|
||||
CPUState *cpu = arg;
|
||||
|
||||
g_assert(tcg_enabled());
|
||||
tcg_cpu_init_cflags(cpu, false);
|
||||
|
||||
assert(tcg_enabled());
|
||||
rcu_register_thread();
|
||||
force_rcu.notify = rr_force_rcu;
|
||||
rcu_add_force_rcu_notifier(&force_rcu);
|
||||
@@ -277,6 +275,9 @@ void rr_start_vcpu_thread(CPUState *cpu)
|
||||
static QemuCond *single_tcg_halt_cond;
|
||||
static QemuThread *single_tcg_cpu_thread;
|
||||
|
||||
g_assert(tcg_enabled());
|
||||
tcg_cpu_init_cflags(cpu, false);
|
||||
|
||||
if (!single_tcg_cpu_thread) {
|
||||
cpu->thread = g_new0(QemuThread, 1);
|
||||
cpu->halt_cond = g_new0(QemuCond, 1);
|
||||
|
||||
+51
-966
File diff suppressed because it is too large
Load Diff
@@ -157,7 +157,7 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
|
||||
tb = db->tb;
|
||||
|
||||
/* Use slow path if first page is MMIO. */
|
||||
if (unlikely(tb->page_addr[0] == -1)) {
|
||||
if (unlikely(tb_page_addr0(tb) == -1)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -169,13 +169,14 @@ static void *translator_access(CPUArchState *env, DisasContextBase *db,
|
||||
host = db->host_addr[1];
|
||||
base = TARGET_PAGE_ALIGN(db->pc_first);
|
||||
if (host == NULL) {
|
||||
tb->page_addr[1] =
|
||||
tb_page_addr_t phys_page =
|
||||
get_page_addr_code_hostp(env, base, &db->host_addr[1]);
|
||||
/* We cannot handle MMIO as second page. */
|
||||
assert(phys_page != -1);
|
||||
tb_set_page_addr1(tb, phys_page);
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
page_protect(end);
|
||||
#endif
|
||||
/* We cannot handle MMIO as second page. */
|
||||
assert(tb->page_addr[1] != -1);
|
||||
host = db->host_addr[1];
|
||||
}
|
||||
|
||||
|
||||
@@ -210,6 +210,48 @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
|
||||
return addr;
|
||||
}
|
||||
|
||||
void page_reset_target_data(target_ulong start, target_ulong end)
|
||||
{
|
||||
#ifdef TARGET_PAGE_DATA_SIZE
|
||||
target_ulong addr, len;
|
||||
|
||||
/*
|
||||
* This function should never be called with addresses outside the
|
||||
* guest address space. If this assert fires, it probably indicates
|
||||
* a missing call to h2g_valid.
|
||||
*/
|
||||
assert(end - 1 <= GUEST_ADDR_MAX);
|
||||
assert(start < end);
|
||||
assert_memory_lock();
|
||||
|
||||
start = start & TARGET_PAGE_MASK;
|
||||
end = TARGET_PAGE_ALIGN(end);
|
||||
|
||||
for (addr = start, len = end - start;
|
||||
len != 0;
|
||||
len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
|
||||
PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
|
||||
|
||||
g_free(p->target_data);
|
||||
p->target_data = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef TARGET_PAGE_DATA_SIZE
|
||||
void *page_get_target_data(target_ulong address)
|
||||
{
|
||||
PageDesc *p = page_find(address >> TARGET_PAGE_BITS);
|
||||
void *ret = p->target_data;
|
||||
|
||||
if (!ret) {
|
||||
ret = g_malloc0(TARGET_PAGE_DATA_SIZE);
|
||||
p->target_data = ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The softmmu versions of these helpers are in cputlb.c. */
|
||||
|
||||
/*
|
||||
|
||||
@@ -663,7 +663,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
page_dump(stdout);
|
||||
printf("\n");
|
||||
#endif
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
mmap_unlock();
|
||||
return start;
|
||||
fail:
|
||||
@@ -769,7 +768,6 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
|
||||
if (ret == 0) {
|
||||
page_set_flags(start, start + len, 0);
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
}
|
||||
mmap_unlock();
|
||||
return ret;
|
||||
|
||||
@@ -277,7 +277,7 @@ void list_cpus(const char *optarg)
|
||||
void tb_invalidate_phys_addr(target_ulong addr)
|
||||
{
|
||||
mmap_lock();
|
||||
tb_invalidate_phys_page_range(addr, addr + 1);
|
||||
tb_invalidate_phys_page(addr);
|
||||
mmap_unlock();
|
||||
}
|
||||
#else
|
||||
@@ -298,7 +298,7 @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs)
|
||||
return;
|
||||
}
|
||||
ram_addr = memory_region_get_ram_addr(mr) + addr;
|
||||
tb_invalidate_phys_page_range(ram_addr, ram_addr + 1);
|
||||
tb_invalidate_phys_page(ram_addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+6
-16
@@ -281,28 +281,18 @@ void page_reset_target_data(target_ulong start, target_ulong end);
|
||||
int page_check_range(target_ulong start, target_ulong len, int flags);
|
||||
|
||||
/**
|
||||
* page_alloc_target_data(address, size)
|
||||
* page_get_target_data(address)
|
||||
* @address: guest virtual address
|
||||
* @size: size of data to allocate
|
||||
*
|
||||
* Allocate @size bytes of out-of-band data to associate with the
|
||||
* guest page at @address. If the page is not mapped, NULL will
|
||||
* be returned. If there is existing data associated with @address,
|
||||
* no new memory will be allocated.
|
||||
* Return TARGET_PAGE_DATA_SIZE bytes of out-of-band data to associate
|
||||
* with the guest page at @address, allocating it if necessary. The
|
||||
* caller should already have verified that the address is valid.
|
||||
*
|
||||
* The memory will be freed when the guest page is deallocated,
|
||||
* e.g. with the munmap system call.
|
||||
*/
|
||||
void *page_alloc_target_data(target_ulong address, size_t size);
|
||||
|
||||
/**
|
||||
* page_get_target_data(address)
|
||||
* @address: guest virtual address
|
||||
*
|
||||
* Return any out-of-bound memory assocated with the guest page
|
||||
* at @address, as per page_alloc_target_data.
|
||||
*/
|
||||
void *page_get_target_data(target_ulong address);
|
||||
void *page_get_target_data(target_ulong address)
|
||||
__attribute__((returns_nonnull));
|
||||
#endif
|
||||
|
||||
CPUArchState *cpu_copy(CPUArchState *env);
|
||||
|
||||
+23
-12
@@ -39,9 +39,6 @@ typedef ram_addr_t tb_page_addr_t;
|
||||
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
|
||||
#endif
|
||||
|
||||
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
|
||||
target_ulong *data);
|
||||
|
||||
/**
|
||||
* cpu_restore_state:
|
||||
* @cpu: the vCPU state is to be restore to
|
||||
@@ -610,18 +607,40 @@ static inline uint32_t tb_cflags(const TranslationBlock *tb)
|
||||
return qatomic_read(&tb->cflags);
|
||||
}
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
|
||||
{
|
||||
return tb->page_addr[0];
|
||||
}
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr1(const TranslationBlock *tb)
|
||||
{
|
||||
return tb->page_addr[1];
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr0(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
tb->page_addr[0] = addr;
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr1(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
tb->page_addr[1] = addr;
|
||||
}
|
||||
|
||||
/* current cflags for hashing/comparison */
|
||||
uint32_t curr_cflags(CPUState *cpu);
|
||||
|
||||
/* TranslationBlock invalidate API */
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void tb_invalidate_phys_addr(target_ulong addr);
|
||||
void tb_invalidate_phys_range(target_ulong start, target_ulong end);
|
||||
#else
|
||||
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
|
||||
#endif
|
||||
void tb_flush(CPUState *cpu);
|
||||
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end);
|
||||
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
|
||||
|
||||
/* GETPC is the true target of the return instruction that we'll execute. */
|
||||
@@ -642,14 +661,6 @@ extern __thread uintptr_t tci_tb_ptr;
|
||||
smaller than 4 bytes, so we don't worry about special-casing this. */
|
||||
#define GETPC_ADJ 2
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
|
||||
void assert_no_pages_locked(void);
|
||||
#else
|
||||
static inline void assert_no_pages_locked(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/**
|
||||
|
||||
@@ -147,8 +147,6 @@ static inline void qemu_ram_block_writeback(RAMBlock *block)
|
||||
#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1)
|
||||
#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
|
||||
|
||||
void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end);
|
||||
|
||||
static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
|
||||
@@ -29,7 +29,7 @@ void page_collection_unlock(struct page_collection *set);
|
||||
void tb_invalidate_phys_page_fast(struct page_collection *pages,
|
||||
tb_page_addr_t start, int len,
|
||||
uintptr_t retaddr);
|
||||
void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
|
||||
void tb_invalidate_phys_page(tb_page_addr_t addr);
|
||||
void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
||||
@@ -31,6 +31,17 @@ struct TCGCPUOps {
|
||||
* function to restore all the state, and register it here.
|
||||
*/
|
||||
void (*synchronize_from_tb)(CPUState *cpu, const TranslationBlock *tb);
|
||||
/**
|
||||
* @restore_state_to_opc: Synchronize state from INDEX_op_start_insn
|
||||
*
|
||||
* This is called when we unwind state in the middle of a TB,
|
||||
* usually before raising an exception. Set all part of the CPU
|
||||
* state which are tracked insn-by-insn in the target-specific
|
||||
* arguments to start_insn, passed as @data.
|
||||
*/
|
||||
void (*restore_state_to_opc)(CPUState *cpu, const TranslationBlock *tb,
|
||||
const uint64_t *data);
|
||||
|
||||
/** @cpu_exec_enter: Callback for cpu_exec preparation */
|
||||
void (*cpu_exec_enter)(CPUState *cpu);
|
||||
/** @cpu_exec_exit: Callback for cpu_exec cleanup */
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
|
||||
#define qatomic_read(ptr) \
|
||||
({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_read__nocheck(ptr); \
|
||||
})
|
||||
|
||||
@@ -141,7 +141,7 @@
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELAXED)
|
||||
|
||||
#define qatomic_set(ptr, i) do { \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_set__nocheck(ptr, i); \
|
||||
} while(0)
|
||||
|
||||
@@ -159,27 +159,27 @@
|
||||
|
||||
#define qatomic_rcu_read(ptr) \
|
||||
({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
typeof_strip_qual(*ptr) _val; \
|
||||
qatomic_rcu_read__nocheck(ptr, &_val); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define qatomic_rcu_set(ptr, i) do { \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
|
||||
} while(0)
|
||||
|
||||
#define qatomic_load_acquire(ptr) \
|
||||
({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
typeof_strip_qual(*ptr) _val; \
|
||||
__atomic_load(ptr, &_val, __ATOMIC_ACQUIRE); \
|
||||
_val; \
|
||||
})
|
||||
|
||||
#define qatomic_store_release(ptr, i) do { \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
|
||||
} while(0)
|
||||
|
||||
@@ -191,7 +191,7 @@
|
||||
})
|
||||
|
||||
#define qatomic_xchg(ptr, i) ({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_xchg__nocheck(ptr, i); \
|
||||
})
|
||||
|
||||
@@ -204,7 +204,7 @@
|
||||
})
|
||||
|
||||
#define qatomic_cmpxchg(ptr, old, new) ({ \
|
||||
QEMU_BUILD_BUG_ON(sizeof(*ptr) > ATOMIC_REG_SIZE); \
|
||||
qemu_build_assert(sizeof(*ptr) <= ATOMIC_REG_SIZE); \
|
||||
qatomic_cmpxchg__nocheck(ptr, old, new); \
|
||||
})
|
||||
|
||||
|
||||
@@ -186,6 +186,14 @@ void QEMU_ERROR("code path is reachable")
|
||||
#define qemu_build_not_reached() g_assert_not_reached()
|
||||
#endif
|
||||
|
||||
/**
|
||||
* qemu_build_assert()
|
||||
*
|
||||
* The compiler, during optimization, is expected to prove that the
|
||||
* assertion is true.
|
||||
*/
|
||||
#define qemu_build_assert(test) while (!(test)) qemu_build_not_reached()
|
||||
|
||||
/*
|
||||
* According to waitpid man page:
|
||||
* WCOREDUMP
|
||||
|
||||
@@ -227,7 +227,7 @@ struct QemuSpin {
|
||||
|
||||
static inline void qemu_spin_init(QemuSpin *spin)
|
||||
{
|
||||
__sync_lock_release(&spin->value);
|
||||
qatomic_set(&spin->value, 0);
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_create(spin, __tsan_mutex_not_static);
|
||||
#endif
|
||||
@@ -246,7 +246,7 @@ static inline void qemu_spin_lock(QemuSpin *spin)
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_lock(spin, 0);
|
||||
#endif
|
||||
while (unlikely(__sync_lock_test_and_set(&spin->value, true))) {
|
||||
while (unlikely(qatomic_xchg(&spin->value, 1))) {
|
||||
while (qatomic_read(&spin->value)) {
|
||||
cpu_relax();
|
||||
}
|
||||
@@ -261,7 +261,7 @@ static inline bool qemu_spin_trylock(QemuSpin *spin)
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_lock(spin, __tsan_mutex_try_lock);
|
||||
#endif
|
||||
bool busy = __sync_lock_test_and_set(&spin->value, true);
|
||||
bool busy = qatomic_xchg(&spin->value, true);
|
||||
#ifdef CONFIG_TSAN
|
||||
unsigned flags = __tsan_mutex_try_lock;
|
||||
flags |= busy ? __tsan_mutex_try_lock_failed : 0;
|
||||
@@ -280,7 +280,7 @@ static inline void qemu_spin_unlock(QemuSpin *spin)
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_pre_unlock(spin, 0);
|
||||
#endif
|
||||
__sync_lock_release(&spin->value);
|
||||
qatomic_store_release(&spin->value, 0);
|
||||
#ifdef CONFIG_TSAN
|
||||
__tsan_mutex_post_unlock(spin, 0);
|
||||
#endif
|
||||
|
||||
@@ -182,7 +182,6 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
|
||||
}
|
||||
|
||||
page_set_flags(start, start + len, page_flags);
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
ret = 0;
|
||||
|
||||
error:
|
||||
@@ -662,7 +661,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int target_prot,
|
||||
qemu_log_unlock(f);
|
||||
}
|
||||
}
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
mmap_unlock();
|
||||
return start;
|
||||
fail:
|
||||
@@ -766,7 +764,6 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
|
||||
if (ret == 0) {
|
||||
page_set_flags(start, start + len, 0);
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
}
|
||||
mmap_unlock();
|
||||
return ret;
|
||||
@@ -856,7 +853,6 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
|
||||
page_set_flags(new_addr, new_addr + new_size,
|
||||
prot | PAGE_VALID | PAGE_RESET);
|
||||
}
|
||||
tb_invalidate_phys_range(new_addr, new_addr + new_size);
|
||||
mmap_unlock();
|
||||
return new_addr;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user