mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/rth-gitlab/tags/pull-tcg-20210914-4' into staging
Fix translation race condition for user-only. Fix tcg/i386 encoding for VPSLLVQ, VPSRLVQ. Fix tcg/arm tcg_out_vec_op signature. Fix tcg/ppc (32bit) build with clang. Remove dupluate TCG_KICK_PERIOD definition. Remove unused tcg_global_reg_new. Restrict cpu_exec_interrupt and its callees to sysemu. Cleanups for tcg/arm. # gpg: Signature made Tue 14 Sep 2021 20:28:35 BST # 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 * remotes/rth-gitlab/tags/pull-tcg-20210914-4: (43 commits) tcg/arm: More use of the TCGReg enum tcg/arm: More use of the ARMInsn enum tcg/arm: Give enum arm_cond_code_e a typedef and use it tcg/arm: Drop inline markers tcg/arm: Simplify usage of encode_imm tcg/arm: Split out tcg_out_ldstm tcg/arm: Support armv4t in tcg_out_goto and tcg_out_call tcg/arm: Simplify use_armv5t_instructions tcg/arm: Standardize on tcg_out_<branch>_{reg,imm} tcg/arm: Remove fallback definition of __ARM_ARCH accel/tcg/user-exec: Fix read-modify-write of code on s390 hosts user: Remove cpu_get_pic_interrupt() stubs accel/tcg: Restrict TCGCPUOps::cpu_exec_interrupt() to sysemu target/xtensa: Restrict cpu_exec_interrupt() handler to sysemu target/rx: Restrict cpu_exec_interrupt() handler to sysemu target/sparc: Restrict cpu_exec_interrupt() handler to sysemu target/sh4: Restrict cpu_exec_interrupt() handler to sysemu target/riscv: Restrict cpu_exec_interrupt() handler to sysemu target/ppc: Restrict cpu_exec_interrupt() handler to sysemu target/openrisc: Restrict cpu_exec_interrupt() handler to sysemu ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -651,8 +651,8 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
loop */
|
||||
#if defined(TARGET_I386)
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
cc->tcg_ops->do_interrupt(cpu);
|
||||
#endif
|
||||
cc->tcg_ops->fake_user_interrupt(cpu);
|
||||
#endif /* TARGET_I386 */
|
||||
*ret = cpu->exception_index;
|
||||
cpu->exception_index = -1;
|
||||
return true;
|
||||
@@ -685,6 +685,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/*
|
||||
* CPU_INTERRUPT_POLL is a virtual event which gets converted into a
|
||||
* "real" interrupt event later. It does not need to be recorded for
|
||||
@@ -698,12 +699,11 @@ static inline bool need_replay_interrupt(int interrupt_request)
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
TranslationBlock **last_tb)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
/* Clear the interrupt flag now since we're processing
|
||||
* cpu->interrupt_request and cpu->exit_request.
|
||||
* Ensure zeroing happens before reading cpu->exit_request or
|
||||
@@ -725,6 +725,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
qemu_mutex_unlock_iothread();
|
||||
return true;
|
||||
}
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (replay_mode == REPLAY_MODE_PLAY && !replay_has_interrupt()) {
|
||||
/* Do nothing */
|
||||
} else if (interrupt_request & CPU_INTERRUPT_HALT) {
|
||||
@@ -753,12 +754,14 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
qemu_mutex_unlock_iothread();
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
#endif /* !TARGET_I386 */
|
||||
/* The target hook has 3 exit conditions:
|
||||
False when the interrupt isn't processed,
|
||||
True when it is, and we should restart on a new TB,
|
||||
and via longjmp via cpu_loop_exit. */
|
||||
else {
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu);
|
||||
|
||||
if (cc->tcg_ops->cpu_exec_interrupt &&
|
||||
cc->tcg_ops->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
if (need_replay_interrupt(interrupt_request)) {
|
||||
@@ -777,6 +780,7 @@ static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||
* reload the 'interrupt_request' value */
|
||||
interrupt_request = cpu->interrupt_request;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
if (interrupt_request & CPU_INTERRUPT_EXITTB) {
|
||||
cpu->interrupt_request &= ~CPU_INTERRUPT_EXITTB;
|
||||
/* ensure that no TB jump will be modified as
|
||||
|
||||
@@ -60,8 +60,6 @@ void rr_kick_vcpu_thread(CPUState *unused)
|
||||
static QEMUTimer *rr_kick_vcpu_timer;
|
||||
static CPUState *rr_current_cpu;
|
||||
|
||||
#define TCG_KICK_PERIOD (NANOSECONDS_PER_SECOND / 10)
|
||||
|
||||
static inline int64_t rr_next_kick_time(void)
|
||||
{
|
||||
return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + TCG_KICK_PERIOD;
|
||||
|
||||
+34
-25
@@ -1297,31 +1297,8 @@ static inline void tb_page_add(PageDesc *p, TranslationBlock *tb,
|
||||
invalidate_page_bitmap(p);
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
if (p->flags & PAGE_WRITE) {
|
||||
target_ulong addr;
|
||||
PageDesc *p2;
|
||||
int prot;
|
||||
|
||||
/* force the host page as non writable (writes will have a
|
||||
page fault + mprotect overhead) */
|
||||
page_addr &= qemu_host_page_mask;
|
||||
prot = 0;
|
||||
for (addr = page_addr; addr < page_addr + qemu_host_page_size;
|
||||
addr += TARGET_PAGE_SIZE) {
|
||||
|
||||
p2 = page_find(addr >> TARGET_PAGE_BITS);
|
||||
if (!p2) {
|
||||
continue;
|
||||
}
|
||||
prot |= p2->flags;
|
||||
p2->flags &= ~PAGE_WRITE;
|
||||
}
|
||||
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
|
||||
(prot & PAGE_BITS) & ~PAGE_WRITE);
|
||||
if (DEBUG_TB_INVALIDATE_GATE) {
|
||||
printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
|
||||
}
|
||||
}
|
||||
/* translator_loop() must have made all TB pages non-writable */
|
||||
assert(!(p->flags & PAGE_WRITE));
|
||||
#else
|
||||
/* if some code is already present, then the pages are already
|
||||
protected. So we handle the case where only the first TB is
|
||||
@@ -2394,6 +2371,38 @@ int page_check_range(target_ulong start, target_ulong len, int flags)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void page_protect(tb_page_addr_t page_addr)
|
||||
{
|
||||
target_ulong addr;
|
||||
PageDesc *p;
|
||||
int prot;
|
||||
|
||||
p = page_find(page_addr >> TARGET_PAGE_BITS);
|
||||
if (p && (p->flags & PAGE_WRITE)) {
|
||||
/*
|
||||
* Force the host page as non writable (writes will have a page fault +
|
||||
* mprotect overhead).
|
||||
*/
|
||||
page_addr &= qemu_host_page_mask;
|
||||
prot = 0;
|
||||
for (addr = page_addr; addr < page_addr + qemu_host_page_size;
|
||||
addr += TARGET_PAGE_SIZE) {
|
||||
|
||||
p = page_find(addr >> TARGET_PAGE_BITS);
|
||||
if (!p) {
|
||||
continue;
|
||||
}
|
||||
prot |= p->flags;
|
||||
p->flags &= ~PAGE_WRITE;
|
||||
}
|
||||
mprotect(g2h_untagged(page_addr), qemu_host_page_size,
|
||||
(prot & PAGE_BITS) & ~PAGE_WRITE);
|
||||
if (DEBUG_TB_INVALIDATE_GATE) {
|
||||
printf("protecting code page: 0x" TB_PAGE_ADDR_FMT "\n", page_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* called from signal handler: invalidate the code and unprotect the
|
||||
* page. Return 0 if the fault was not handled, 1 if it was handled,
|
||||
* and 2 if it was handled but the caller must cause the TB to be
|
||||
|
||||
@@ -42,6 +42,15 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
|
||||
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
|
||||
}
|
||||
|
||||
static inline void translator_page_protect(DisasContextBase *dcbase,
|
||||
target_ulong pc)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK;
|
||||
page_protect(pc);
|
||||
#endif
|
||||
}
|
||||
|
||||
void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
CPUState *cpu, TranslationBlock *tb, int max_insns)
|
||||
{
|
||||
@@ -56,6 +65,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
db->num_insns = 0;
|
||||
db->max_insns = max_insns;
|
||||
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
|
||||
translator_page_protect(db, db->pc_next);
|
||||
|
||||
ops->init_disas_context(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
@@ -137,3 +147,32 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
|
||||
target_ulong pc, size_t len)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
target_ulong end = pc + len - 1;
|
||||
|
||||
if (end > dcbase->page_protect_end) {
|
||||
translator_page_protect(dcbase, end);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
|
||||
type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
|
||||
abi_ptr pc, bool do_swap) \
|
||||
{ \
|
||||
translator_maybe_page_protect(dcbase, pc, sizeof(type)); \
|
||||
type ret = load_fn(env, pc); \
|
||||
if (do_swap) { \
|
||||
ret = swap_fn(ret); \
|
||||
} \
|
||||
plugin_insn_append(&ret, sizeof(ret)); \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
|
||||
|
||||
#undef GEN_TRANSLATOR_LD
|
||||
|
||||
+41
-7
@@ -680,18 +680,26 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
|
||||
pc = uc->uc_mcontext.psw.addr;
|
||||
|
||||
/* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
|
||||
of the normal 2 arguments. The 3rd argument contains the "int_code"
|
||||
from the hardware which does in fact contain the is_write value.
|
||||
The rt signal handler, as far as I can tell, does not give this value
|
||||
at all. Not that we could get to it from here even if it were. */
|
||||
/* ??? This is not even close to complete, since it ignores all
|
||||
of the read-modify-write instructions. */
|
||||
/*
|
||||
* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
|
||||
* of the normal 2 arguments. The 4th argument contains the "Translation-
|
||||
* Exception Identification for DAT Exceptions" from the hardware (aka
|
||||
* "int_parm_long"), which does in fact contain the is_write value.
|
||||
* The rt signal handler, as far as I can tell, does not give this value
|
||||
* at all. Not that we could get to it from here even if it were.
|
||||
* So fall back to parsing instructions. Treat read-modify-write ones as
|
||||
* writes, which is not fully correct, but for tracking self-modifying code
|
||||
* this is better than treating them as reads. Checking si_addr page flags
|
||||
* might be a viable improvement, albeit a racy one.
|
||||
*/
|
||||
/* ??? This is not even close to complete. */
|
||||
pinsn = (uint16_t *)pc;
|
||||
switch (pinsn[0] >> 8) {
|
||||
case 0x50: /* ST */
|
||||
case 0x42: /* STC */
|
||||
case 0x40: /* STH */
|
||||
case 0xba: /* CS */
|
||||
case 0xbb: /* CDS */
|
||||
is_write = 1;
|
||||
break;
|
||||
case 0xc4: /* RIL format insns */
|
||||
@@ -702,6 +710,12 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
is_write = 1;
|
||||
}
|
||||
break;
|
||||
case 0xc8: /* SSF format insns */
|
||||
switch (pinsn[0] & 0xf) {
|
||||
case 0x2: /* CSST */
|
||||
is_write = 1;
|
||||
}
|
||||
break;
|
||||
case 0xe3: /* RXY format insns */
|
||||
switch (pinsn[2] & 0xff) {
|
||||
case 0x50: /* STY */
|
||||
@@ -715,7 +729,27 @@ int cpu_signal_handler(int host_signum, void *pinfo,
|
||||
is_write = 1;
|
||||
}
|
||||
break;
|
||||
case 0xeb: /* RSY format insns */
|
||||
switch (pinsn[2] & 0xff) {
|
||||
case 0x14: /* CSY */
|
||||
case 0x30: /* CSG */
|
||||
case 0x31: /* CDSY */
|
||||
case 0x3e: /* CDSG */
|
||||
case 0xe4: /* LANG */
|
||||
case 0xe6: /* LAOG */
|
||||
case 0xe7: /* LAXG */
|
||||
case 0xe8: /* LAAG */
|
||||
case 0xea: /* LAALG */
|
||||
case 0xf4: /* LAN */
|
||||
case 0xf6: /* LAO */
|
||||
case 0xf7: /* LAX */
|
||||
case 0xfa: /* LAAL */
|
||||
case 0xf8: /* LAA */
|
||||
is_write = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,6 @@ uint64_t cpu_get_tsc(CPUX86State *env)
|
||||
return cpu_get_host_ticks();
|
||||
}
|
||||
|
||||
int cpu_get_pic_interrupt(CPUX86State *env)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bsd_i386_write_dt(void *ptr, unsigned long addr, unsigned long limit,
|
||||
int flags)
|
||||
{
|
||||
|
||||
@@ -33,11 +33,6 @@ uint64_t cpu_get_tsc(CPUX86State *env)
|
||||
return cpu_get_host_ticks();
|
||||
}
|
||||
|
||||
int cpu_get_pic_interrupt(CPUX86State *env)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bsd_x86_64_write_dt(void *ptr, unsigned long addr,
|
||||
unsigned long limit, int flags)
|
||||
{
|
||||
|
||||
@@ -33,6 +33,7 @@ void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end);
|
||||
void tb_check_watchpoint(CPUState *cpu, uintptr_t retaddr);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
void page_protect(tb_page_addr_t page_addr);
|
||||
int page_unprotect(target_ulong address, uintptr_t pc);
|
||||
#endif
|
||||
|
||||
|
||||
+26
-18
@@ -23,6 +23,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/plugin-gen.h"
|
||||
#include "exec/translate-all.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
|
||||
@@ -74,6 +75,17 @@ typedef struct DisasContextBase {
|
||||
int num_insns;
|
||||
int max_insns;
|
||||
bool singlestep_enabled;
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/*
|
||||
* Guest address of the last byte of the last protected page.
|
||||
*
|
||||
* Pages containing the translated instructions are made non-writable in
|
||||
* order to achieve consistency in case another thread is modifying the
|
||||
* code while translate_insn() fetches the instruction bytes piecemeal.
|
||||
* Such writer threads are blocked on mmap_lock() in page_unprotect().
|
||||
*/
|
||||
target_ulong page_protect_end;
|
||||
#endif
|
||||
} DisasContextBase;
|
||||
|
||||
/**
|
||||
@@ -156,27 +168,23 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
|
||||
*/
|
||||
|
||||
#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
|
||||
static inline type \
|
||||
fullname ## _swap(CPUArchState *env, abi_ptr pc, bool do_swap) \
|
||||
type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
|
||||
abi_ptr pc, bool do_swap); \
|
||||
static inline type fullname(CPUArchState *env, \
|
||||
DisasContextBase *dcbase, abi_ptr pc) \
|
||||
{ \
|
||||
type ret = load_fn(env, pc); \
|
||||
if (do_swap) { \
|
||||
ret = swap_fn(ret); \
|
||||
} \
|
||||
plugin_insn_append(&ret, sizeof(ret)); \
|
||||
return ret; \
|
||||
} \
|
||||
\
|
||||
static inline type fullname(CPUArchState *env, abi_ptr pc) \
|
||||
{ \
|
||||
return fullname ## _swap(env, pc, false); \
|
||||
return fullname ## _swap(env, dcbase, pc, false); \
|
||||
}
|
||||
|
||||
GEN_TRANSLATOR_LD(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */)
|
||||
GEN_TRANSLATOR_LD(translator_ldsw, int16_t, cpu_ldsw_code, bswap16)
|
||||
GEN_TRANSLATOR_LD(translator_lduw, uint16_t, cpu_lduw_code, bswap16)
|
||||
GEN_TRANSLATOR_LD(translator_ldl, uint32_t, cpu_ldl_code, bswap32)
|
||||
GEN_TRANSLATOR_LD(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
|
||||
#define FOR_EACH_TRANSLATOR_LD(F) \
|
||||
F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
|
||||
F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) \
|
||||
F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
|
||||
F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
|
||||
F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
|
||||
|
||||
FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
|
||||
|
||||
#undef GEN_TRANSLATOR_LD
|
||||
|
||||
#endif /* EXEC__TRANSLATOR_H */
|
||||
|
||||
@@ -35,16 +35,6 @@ struct TCGCPUOps {
|
||||
void (*cpu_exec_enter)(CPUState *cpu);
|
||||
/** @cpu_exec_exit: Callback for cpu_exec cleanup */
|
||||
void (*cpu_exec_exit)(CPUState *cpu);
|
||||
/** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
|
||||
bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
|
||||
/**
|
||||
* @do_interrupt: Callback for interrupt handling.
|
||||
*
|
||||
* note that this is in general SOFTMMU only, but it actually isn't
|
||||
* because of an x86 hack (accel/tcg/cpu-exec.c), so we cannot put it
|
||||
* in the SOFTMMU section in general.
|
||||
*/
|
||||
void (*do_interrupt)(CPUState *cpu);
|
||||
/**
|
||||
* @tlb_fill: Handle a softmmu tlb miss or user-only address fault
|
||||
*
|
||||
@@ -61,7 +51,23 @@ struct TCGCPUOps {
|
||||
void (*debug_excp_handler)(CPUState *cpu);
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
#if defined(CONFIG_USER_ONLY) && defined(TARGET_I386)
|
||||
/**
|
||||
* @fake_user_interrupt: Callback for 'fake exception' handling.
|
||||
*
|
||||
* Simulate 'fake exception' which will be handled outside the
|
||||
* cpu execution loop (hack for x86 user mode).
|
||||
*/
|
||||
void (*fake_user_interrupt)(CPUState *cpu);
|
||||
#else
|
||||
/**
|
||||
* @do_interrupt: Callback for interrupt handling.
|
||||
*/
|
||||
void (*do_interrupt)(CPUState *cpu);
|
||||
#endif /* !CONFIG_USER_ONLY || !TARGET_I386 */
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
/** @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec */
|
||||
bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
|
||||
/**
|
||||
* @do_transaction_failed: Callback for handling failed memory transactions
|
||||
* (ie bus faults or external aborts; not MMU faults)
|
||||
|
||||
@@ -843,7 +843,6 @@ static inline void tcg_gen_plugin_cb_end(void)
|
||||
|
||||
#if TARGET_LONG_BITS == 32
|
||||
#define tcg_temp_new() tcg_temp_new_i32()
|
||||
#define tcg_global_reg_new tcg_global_reg_new_i32
|
||||
#define tcg_global_mem_new tcg_global_mem_new_i32
|
||||
#define tcg_temp_local_new() tcg_temp_local_new_i32()
|
||||
#define tcg_temp_free tcg_temp_free_i32
|
||||
@@ -851,7 +850,6 @@ static inline void tcg_gen_plugin_cb_end(void)
|
||||
#define tcg_gen_qemu_st_tl tcg_gen_qemu_st_i32
|
||||
#else
|
||||
#define tcg_temp_new() tcg_temp_new_i64()
|
||||
#define tcg_global_reg_new tcg_global_reg_new_i64
|
||||
#define tcg_global_mem_new tcg_global_mem_new_i64
|
||||
#define tcg_temp_local_new() tcg_temp_local_new_i64()
|
||||
#define tcg_temp_free tcg_temp_free_i64
|
||||
|
||||
@@ -120,13 +120,6 @@ const char *qemu_uname_release;
|
||||
by remapping the process stack directly at the right place */
|
||||
unsigned long guest_stack_size = 8 * 1024 * 1024UL;
|
||||
|
||||
#if defined(TARGET_I386)
|
||||
int cpu_get_pic_interrupt(CPUX86State *env)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/***********************************************************/
|
||||
/* Helper routines for implementing atomic operations. */
|
||||
|
||||
|
||||
+1
-1
@@ -218,10 +218,10 @@ static const struct SysemuCPUOps alpha_sysemu_ops = {
|
||||
|
||||
static const struct TCGCPUOps alpha_tcg_ops = {
|
||||
.initialize = alpha_translate_init,
|
||||
.cpu_exec_interrupt = alpha_cpu_exec_interrupt,
|
||||
.tlb_fill = alpha_cpu_tlb_fill,
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
.cpu_exec_interrupt = alpha_cpu_exec_interrupt,
|
||||
.do_interrupt = alpha_cpu_do_interrupt,
|
||||
.do_transaction_failed = alpha_cpu_do_transaction_failed,
|
||||
.do_unaligned_access = alpha_cpu_do_unaligned_access,
|
||||
|
||||
+1
-1
@@ -274,10 +274,10 @@ struct AlphaCPU {
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const VMStateDescription vmstate_alpha_cpu;
|
||||
#endif
|
||||
|
||||
void alpha_cpu_do_interrupt(CPUState *cpu);
|
||||
bool alpha_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags);
|
||||
hwaddr alpha_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
||||
int alpha_cpu_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
|
||||
@@ -293,7 +293,6 @@ bool alpha_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
|
||||
prot, mmu_idx, TARGET_PAGE_SIZE);
|
||||
return true;
|
||||
}
|
||||
#endif /* USER_ONLY */
|
||||
|
||||
void alpha_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
@@ -348,7 +347,6 @@ void alpha_cpu_do_interrupt(CPUState *cs)
|
||||
|
||||
cs->exception_index = -1;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
switch (i) {
|
||||
case EXCP_RESET:
|
||||
i = 0x0000;
|
||||
@@ -404,7 +402,6 @@ void alpha_cpu_do_interrupt(CPUState *cs)
|
||||
|
||||
/* Switch to PALmode. */
|
||||
env->flags |= ENV_FLAG_PAL_MODE;
|
||||
#endif /* !USER_ONLY */
|
||||
}
|
||||
|
||||
bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
@@ -451,6 +448,8 @@ bool alpha_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
void alpha_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
{
|
||||
static const char linux_reg_names[31][4] = {
|
||||
|
||||
@@ -2971,7 +2971,7 @@ static void alpha_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
CPUAlphaState *env = cpu->env_ptr;
|
||||
uint32_t insn = translator_ldl(env, ctx->base.pc_next);
|
||||
uint32_t insn = translator_ldl(env, &ctx->base, ctx->base.pc_next);
|
||||
|
||||
ctx->base.pc_next += 4;
|
||||
ctx->base.is_jmp = translate_one(ctx, insn);
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
/* Load an instruction and return it in the standard little-endian order */
|
||||
static inline uint32_t arm_ldl_code(CPUARMState *env, target_ulong addr,
|
||||
bool sctlr_b)
|
||||
static inline uint32_t arm_ldl_code(CPUARMState *env, DisasContextBase *s,
|
||||
target_ulong addr, bool sctlr_b)
|
||||
{
|
||||
return translator_ldl_swap(env, addr, bswap_code(sctlr_b));
|
||||
return translator_ldl_swap(env, s, addr, bswap_code(sctlr_b));
|
||||
}
|
||||
|
||||
/* Ditto, for a halfword (Thumb) instruction */
|
||||
static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
|
||||
bool sctlr_b)
|
||||
static inline uint16_t arm_lduw_code(CPUARMState *env, DisasContextBase* s,
|
||||
target_ulong addr, bool sctlr_b)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* In big-endian (BE32) mode, adjacent Thumb instructions have been swapped
|
||||
@@ -41,7 +41,7 @@ static inline uint16_t arm_lduw_code(CPUARMState *env, target_ulong addr,
|
||||
addr ^= 2;
|
||||
}
|
||||
#endif
|
||||
return translator_lduw_swap(env, addr, bswap_code(sctlr_b));
|
||||
return translator_lduw_swap(env, s, addr, bswap_code(sctlr_b));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+5
-2
@@ -440,6 +440,8 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||
arm_rebuild_hflags(env);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||
unsigned int target_el,
|
||||
unsigned int cur_el, bool secure,
|
||||
@@ -556,7 +558,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
|
||||
return unmasked || pstate_unmasked;
|
||||
}
|
||||
|
||||
bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
static bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
CPUARMState *env = cs->env_ptr;
|
||||
@@ -608,6 +610,7 @@ bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
cc->tcg_ops->do_interrupt(cs);
|
||||
return true;
|
||||
}
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
void arm_cpu_update_virq(ARMCPU *cpu)
|
||||
{
|
||||
@@ -2010,11 +2013,11 @@ static const struct SysemuCPUOps arm_sysemu_ops = {
|
||||
static const struct TCGCPUOps arm_tcg_ops = {
|
||||
.initialize = arm_translate_init,
|
||||
.synchronize_from_tb = arm_cpu_synchronize_from_tb,
|
||||
.cpu_exec_interrupt = arm_cpu_exec_interrupt,
|
||||
.tlb_fill = arm_cpu_tlb_fill,
|
||||
.debug_excp_handler = arm_debug_excp_handler,
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
.cpu_exec_interrupt = arm_cpu_exec_interrupt,
|
||||
.do_interrupt = arm_cpu_do_interrupt,
|
||||
.do_transaction_failed = arm_cpu_do_transaction_failed,
|
||||
.do_unaligned_access = arm_cpu_do_unaligned_access,
|
||||
|
||||
+1
-2
@@ -1040,11 +1040,10 @@ uint64_t arm_cpu_mp_affinity(int idx, uint8_t clustersz);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const VMStateDescription vmstate_arm_cpu;
|
||||
#endif
|
||||
|
||||
void arm_cpu_do_interrupt(CPUState *cpu);
|
||||
void arm_v7m_cpu_do_interrupt(CPUState *cpu);
|
||||
bool arm_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr,
|
||||
MemTxAttrs *attrs);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
/* CPU models. These are not needed for the AArch64 linux-user build. */
|
||||
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
|
||||
static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cs);
|
||||
@@ -46,7 +46,7 @@ static bool arm_v7m_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* CONFIG_TCG */
|
||||
#endif /* !CONFIG_USER_ONLY && CONFIG_TCG */
|
||||
|
||||
static void arm926_initfn(Object *obj)
|
||||
{
|
||||
@@ -898,11 +898,11 @@ static void pxa270c5_initfn(Object *obj)
|
||||
static const struct TCGCPUOps arm_v7m_tcg_ops = {
|
||||
.initialize = arm_translate_init,
|
||||
.synchronize_from_tb = arm_cpu_synchronize_from_tb,
|
||||
.cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
|
||||
.tlb_fill = arm_cpu_tlb_fill,
|
||||
.debug_excp_handler = arm_debug_excp_handler,
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
.cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt,
|
||||
.do_interrupt = arm_v7m_cpu_do_interrupt,
|
||||
.do_transaction_failed = arm_cpu_do_transaction_failed,
|
||||
.do_unaligned_access = arm_cpu_do_unaligned_access,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user