diff --git a/include/fpu/softfloat-types.h b/include/fpu/softfloat-types.h index 5bcbd041f74f8..a72314ca4e5ca 100644 --- a/include/fpu/softfloat-types.h +++ b/include/fpu/softfloat-types.h @@ -80,6 +80,9 @@ this code that are retained. #ifndef SOFTFLOAT_TYPES_H #define SOFTFLOAT_TYPES_H +#include +#include + /* * Software IEC/IEEE floating-point types. */ diff --git a/include/fpu/softfloat.h b/include/fpu/softfloat.h index a249991e61277..b5a7c120af302 100644 --- a/include/fpu/softfloat.h +++ b/include/fpu/softfloat.h @@ -95,6 +95,7 @@ typedef enum { #include "fpu/softfloat-types.h" #include "fpu/softfloat-helpers.h" +#include /*---------------------------------------------------------------------------- | Routine to raise any or all of the software IEC/IEEE floating-point diff --git a/include/qemu/bswap.h b/include/qemu/bswap.h index 2d3bb8bbeddac..1b712ce9fd1f8 100644 --- a/include/qemu/bswap.h +++ b/include/qemu/bswap.h @@ -1,6 +1,7 @@ #ifndef BSWAP_H #define BSWAP_H +#include "osdep.h" #ifdef CONFIG_MACHINE_BSWAP_H # include # include diff --git a/linux-user/mips/trace_info.h b/linux-user/mips/trace_info.h index ea78cd3e83c1e..2b1b7efd65d6d 100644 --- a/linux-user/mips/trace_info.h +++ b/linux-user/mips/trace_info.h @@ -1,6 +1,7 @@ #pragma once #include "frame_arch.h" +#include const uint64_t frame_arch = frame_arch_mips; -const uint64_t frame_mach = frame_mach_mipsisa32 ; +const uint64_t frame_mach = frame_mach_mipsisa32; diff --git a/linux-user/mips64/trace_info.h b/linux-user/mips64/trace_info.h new file mode 100644 index 0000000000000..65deefe37a682 --- /dev/null +++ b/linux-user/mips64/trace_info.h @@ -0,0 +1,7 @@ +#pragma once + +#include "frame_arch.h" +#include + +const uint64_t frame_arch = frame_arch_mips; +const uint64_t frame_mach = frame_mach_mipsisa64; diff --git a/qobject/block-qdict.c b/qobject/block-qdict.c index b26524429c0dd..bbe6ea4af1f12 100644 --- a/qobject/block-qdict.c +++ b/qobject/block-qdict.c @@ -226,8 +226,8 @@ void qdict_array_split(QDict *src, QList **dst) bool is_subqdict; QDict *subqdict = NULL; char indexstr[32], prefix[32]; - size_t snprintf_ret; + size_t snprintf_ret; snprintf_ret = snprintf(indexstr, 32, "%u", i); assert(snprintf_ret < 32); diff --git a/stubs/replay-tools.c b/stubs/replay-tools.c index 43296b3d4eb75..d2d6c1c93c623 100644 --- a/stubs/replay-tools.c +++ b/stubs/replay-tools.c @@ -7,13 +7,13 @@ bool replay_events_enabled(void) return false; } -int64_t replay_save_clock(unsigned int kind, int64_t clock, int64_t raw_icount) +int64_t replay_save_clock(ReplayClockKind kind, int64_t clock, int64_t raw_icount) { abort(); return 0; } -int64_t replay_read_clock(unsigned int kind, int64_t raw_icount) +int64_t replay_read_clock(ReplayClockKind kind, int64_t raw_icount) { abort(); return 0; diff --git a/target/mips/helper.h b/target/mips/helper.h index cd8a7dc2dfbed..11cf1652e93ee 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -1,4 +1,4 @@ -DEF_HELPER_3(raise_exception_err, noreturn, env, i32, int) +DEF_HELPER_3(raise_exception_err, noreturn, env, i32, i32) DEF_HELPER_2(raise_exception, noreturn, env, i32) DEF_HELPER_1(raise_exception_debug, noreturn, env) @@ -17,13 +17,30 @@ DEF_HELPER_3(lld, tl, env, tl, int) #endif #ifdef HAS_TRACEWRAP -DEF_HELPER_1(trace_newframe, void, tl) -DEF_HELPER_3(trace_endframe, void, env, tl, i32) -DEF_HELPER_2(trace_load_reg, void, i32, i32) -DEF_HELPER_2(trace_store_reg, void, i32, i32) -DEF_HELPER_3(trace_ld, void, env, i32, i32) -DEF_HELPER_3(trace_st, void, env, i32, i32) -#endif //HAS_TRACEWRAP +// trace being/end +DEF_HELPER_1(trace_newframe, void, i64) +DEF_HELPER_2(trace_endframe, void, env, i64) +DEF_HELPER_1(trace_mode, void, ptr) + +// load/store registers +DEF_HELPER_2(trace_load_reg32, void, i32, i32) +DEF_HELPER_2(trace_store_reg32, void, i32, i32) + +// load store memory operands +DEF_HELPER_3(trace_load_mem, void, i32, i32, i32) +DEF_HELPER_3(trace_store_mem, void, i32, i32, i32) +DEF_HELPER_3(trace_load_mem_i64, void, i32, i64, i32) +DEF_HELPER_3(trace_store_mem_i64, void, i32, i64, i32) +#ifdef TARGET_MIPS64 +// load/store registers +DEF_HELPER_2(trace_load_reg64, void, i32, i64) +DEF_HELPER_2(trace_store_reg64, void, i32, i64) + +// load store memory operands +DEF_HELPER_3(trace_load_mem64, void, i64, i64, i32) +DEF_HELPER_3(trace_store_mem64, void, i64, i64, i32) +#endif // TARGET_MIPS64 +#endif // HAS_TRACEWRAP DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 diff --git a/target/mips/tcg/exception.c b/target/mips/tcg/exception.c index 7b3026b105b88..b1cc73daba8a4 100644 --- a/target/mips/tcg/exception.c +++ b/target/mips/tcg/exception.c @@ -43,7 +43,7 @@ target_ulong exception_resume_pc(CPUMIPSState *env) } void helper_raise_exception_err(CPUMIPSState *env, uint32_t exception, - int error_code) + uint32_t error_code) { do_raise_exception_err(env, exception, error_code, 0); } diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index 47db35d7dd9ae..9e4570b3945f1 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1224,6 +1224,100 @@ static const char regnames_LO[][4] = { "LO0", "LO1", "LO2", "LO3", }; +/* +** Include useful headers and defines +*/ +#ifdef HAS_TRACEWRAP +#include +#endif // HAS_TRACEWRAP + +static inline void gen_trace_newframe(uint64_t pc) { +#ifdef HAS_TRACEWRAP + + // will contain machine type information + TCGv_i64 _pc = tcg_const_i64(pc); + gen_helper_trace_newframe(_pc); + tcg_temp_free_i64(_pc); + + TCGv_ptr mt; +#ifdef TARGET_MIPS64 + mt = tcg_const_ptr(FRAME_MODE_MIPS64); +#else // else this is TARGET_MIPS + mt = tcg_const_ptr(FRAME_MODE_MIPS); +#endif // TARGET_MIPS64 + + // set trace mode to mips64 or mips + gen_helper_trace_mode(mt); + tcg_temp_free_ptr(mt); + +#endif // HAS_TRACEWRAP +} + +static inline void gen_trace_endframe(uint64_t pc) { +#ifdef HAS_TRACEWRAP + TCGv_i64 _pc = tcg_const_i64(pc); + gen_helper_trace_endframe(cpu_env, _pc); + tcg_temp_free_i64(_pc); + +#endif // HAS_TRACEWRAP +} + +static void gen_trace_load_reg(int reg, TCGv var) { +#ifdef HAS_TRACEWRAP + + TCGv_i32 r = tcg_const_i32(reg); +#ifdef TARGET_MIPS64 + gen_helper_trace_load_reg64(r, var); +#else + gen_helper_trace_load_reg32(r, var); +#endif + tcg_temp_free_i32(r); + +#endif // HAS_TRACEWRAP +} + +static void gen_trace_store_reg(int reg, TCGv var) { +#ifdef HAS_TRACEWRAP + + TCGv_i32 r = tcg_const_i32(reg); +#ifdef TARGET_MIPS64 + gen_helper_trace_store_reg64(r, var); +#else + gen_helper_trace_store_reg32(r, var); +#endif + tcg_temp_free_i32(r); + +#endif // HAS_TRACEWRAP +} + +static void gen_trace_load_mem(TCGv addr, TCGv val, MemOp op) { +#ifdef HAS_TRACEWRAP + + TCGv_i32 o = tcg_const_i32(op); +#ifdef TARGET_MIPS64 + gen_helper_trace_load_mem64(addr, val, o); +#else + gen_helper_trace_load_mem(addr, val, o); +#endif + tcg_temp_free_i32(o); + +#endif // HAS_TRACEWRAP +} + +static void gen_trace_store_mem(TCGv addr, TCGv val, MemOp op) { +#ifdef HAS_TRACEWRAP + + TCGv_i32 o = tcg_const_i32(op); +#ifdef TARGET_MIPS64 + gen_helper_trace_store_mem64(addr, val, o); +#else + gen_helper_trace_store_mem(addr, val, o); +#endif + tcg_temp_free_i32(o); + +#endif // HAS_TRACEWRAP +} + /* General purpose registers moves. */ void gen_load_gpr(TCGv t, int reg) { @@ -1232,6 +1326,8 @@ void gen_load_gpr(TCGv t, int reg) } else { tcg_gen_mov_tl(t, cpu_gpr[reg]); } + + gen_trace_load_reg(reg, t); } void gen_store_gpr(TCGv t, int reg) @@ -1239,6 +1335,8 @@ void gen_store_gpr(TCGv t, int reg) if (reg != 0) { tcg_gen_mov_tl(cpu_gpr[reg], t); } + + gen_trace_store_reg(reg, t); } #if defined(TARGET_MIPS64) @@ -1249,6 +1347,8 @@ void gen_load_gpr_hi(TCGv_i64 t, int reg) } else { tcg_gen_mov_i64(t, cpu_gpr_hi[reg]); } + + gen_trace_load_reg(reg, t); } void gen_store_gpr_hi(TCGv_i64 t, int reg) @@ -1256,6 +1356,8 @@ void gen_store_gpr_hi(TCGv_i64 t, int reg) if (reg != 0) { tcg_gen_mov_i64(cpu_gpr_hi[reg], t); } + + gen_trace_store_reg(reg, t); } #endif /* TARGET_MIPS64 */ @@ -1264,6 +1366,7 @@ static inline void gen_load_srsgpr(int from, int to) { TCGv t0 = tcg_temp_new(); + // if from == r0 then just move 0 if (from == 0) { tcg_gen_movi_tl(t0, 0); } else { @@ -16033,19 +16136,24 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) int insn_bytes; int is_slot; + // get pc_next and start generating new traceframe + uint64_t pc_next = ctx->base.pc_next; + gen_trace_newframe(pc_next); + + // translate depending on architecture is_slot = ctx->hflags & MIPS_HFLAG_BMASK; if (ctx->insn_flags & ISA_NANOMIPS32) { - ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, &ctx->base, pc_next); insn_bytes = decode_isa_nanomips(env, ctx); } else if (!(ctx->hflags & MIPS_HFLAG_M16)) { - ctx->opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next); + ctx->opcode = translator_ldl(env, &ctx->base, pc_next); insn_bytes = 4; decode_opc(env, ctx); } else if (ctx->insn_flags & ASE_MICROMIPS) { - ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, &ctx->base, pc_next); insn_bytes = decode_isa_micromips(env, ctx); } else if (ctx->insn_flags & ASE_MIPS16) { - ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next); + ctx->opcode = translator_lduw(env, &ctx->base, pc_next); insn_bytes = decode_ase_mips16e(env, ctx); } else { gen_reserved_instruction(ctx); @@ -16074,7 +16182,11 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) if (is_slot) { gen_branch(ctx, insn_bytes); } + + // update pc for next instruction + // and get pc_next ctx->base.pc_next += insn_bytes; + pc_next = ctx->base.pc_next; if (ctx->base.is_jmp != DISAS_NEXT) { return; @@ -16085,10 +16197,13 @@ static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs) * See mips_tr_init_disas_context about single-stepping a branch * together with its delay slot. */ - if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE + if (pc_next - ctx->page_start >= TARGET_PAGE_SIZE && !ctx->base.singlestep_enabled) { ctx->base.is_jmp = DISAS_TOO_MANY; } + + // end the frame + gen_trace_endframe(pc_next); } static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs) diff --git a/target/mips/trace_helper.c b/target/mips/trace_helper.c index db098d5844bfe..25b0ee0bb1f84 100644 --- a/target/mips/trace_helper.c +++ b/target/mips/trace_helper.c @@ -1,25 +1,31 @@ #include #include "cpu.h" -#include "helper.h" #include "tracewrap.h" #include "qemu/log.h" +#include "exec/helper-proto.h" +#include "exec/memop.h" + +#define MIPS_INSN_SIZE 4 const char *regs[] = {"r0","at","v0","v1","a0","a1","a2","a3","t0","t1","t2","t3","t4","t5","t6","t7","s0","s1","s2","s3","s4","s5","s6","s7","t8","t9","k0","k1","gp","sp","s8","ra","LO","HI"}; static const int reg_max = sizeof(regs) / sizeof(regs[0]); -void HELPER(trace_newframe)(target_ulong pc) -{ - qemu_trace_newframe(pc, 0); -} - -void HELPER(trace_endframe)(CPUMIPSState *env, target_ulong old_pc, uint32_t size) -{ - qemu_trace_endframe(env, old_pc, size); -} - -OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) -{ +void HELPER(trace_newframe)(uint64_t pc) { qemu_trace_newframe(pc, 0); } +void HELPER(trace_endframe)(CPUMIPSState *env, uint64_t pc) { qemu_trace_endframe(env, pc, MIPS_INSN_SIZE); } +void HELPER(trace_mode)(void *mode) { qemu_trace_set_mode(mode); } + +/** + * Load/Store a value from/to a register + * + * @param reg is index into the @c regs array declared at top + * @param val is value to be stored + * @param len is length (size) in bytes of val + * @param ls if 0 means this is a LOAD operation, otherwise STORE operation + * + * @return OperandInfo + * */ +OperandInfo * build_load_store_reg_op(uint32_t reg, uint64_t val, size_t len, int ls) { RegOperand * ro = g_new(RegOperand,1); reg_operand__init(ro); ro->name = g_strdup(reg < reg_max ? regs[reg] : "UNKOWN"); @@ -27,6 +33,7 @@ OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) OperandInfoSpecific *ois = g_new(OperandInfoSpecific,1); operand_info_specific__init(ois); ois->reg_operand = ro; + OperandUsage *ou = g_new(OperandUsage,1); operand_usage__init(ou); if (ls == 0) @@ -35,62 +42,69 @@ OperandInfo * load_store_reg(uint32_t reg, uint32_t val, int ls) } else { ou->written = 1; } + OperandInfo *oi = g_new(OperandInfo,1); operand_info__init(oi); oi->bit_length = 0; oi->operand_info_specific = ois; oi->operand_usage = ou; - oi->value.len = 4; + oi->value.len = len; oi->value.data = g_malloc(oi->value.len); - memcpy(oi->value.data, &val, 4); - return oi; -} -void HELPER(trace_load_reg)(uint32_t reg, uint32_t val) -{ - qemu_log("This register (r%d) was read. Value 0x%x\n", reg, val); - - //r0 always reads 0 - OperandInfo *oi = load_store_reg(reg, (reg != 0) ? val : 0, 0); + // if reg == 0 (means r0), it should always read 0 + if(reg == 0) { + memset(oi->value.data, 0, sizeof(val)); + } else { + memcpy(oi->value.data, &val, len); + } - qemu_trace_add_operand(oi, 0x1); + return oi; } -void HELPER(trace_store_reg)(uint32_t reg, uint32_t val) -{ - qemu_log("This register (r%d) was written. Value: 0x%x\n", reg, val); - - OperandInfo *oi = load_store_reg(reg, val, 1); - - qemu_trace_add_operand(oi, 0x2); +/** + * load/store operations for 32 bit registers + * function is declared in tracewrap.h and is defined per architecture + * */ +OperandInfo *load_store_reg(uint32_t reg, uint32_t val, int ls) { + return build_load_store_reg_op(reg, val, sizeof(val), ls); } - -//void HELPER(trace_load_eflags)(CPUMIPSState *env) -//{ -// OperandInfo *oi = load_store_reg(REG_EFLAGS, cpu_compute_eflags(env), 0); -// -// qemu_trace_add_operand(oi, 0x1); -//} -// -//void HELPER(trace_store_eflags)(CPUMIPSState *env) -//{ -// OperandInfo *oi = load_store_reg(REG_EFLAGS, cpu_compute_eflags(env), 1); -// -// qemu_trace_add_operand(oi, 0x2); -//} -// - -// TODO: signature has changed, see arm -OperandInfo * load_store_mem(uint32_t addr, uint32_t val, int ls, int len) { +void HELPER(trace_load_reg32)(uint32_t reg, uint32_t val) { load_store_reg(reg, val, 0); } +void HELPER(trace_store_reg32)(uint32_t reg, uint32_t val) { load_store_reg(reg, val, 1); } + +#ifdef TARGET_MIPS64 +/** + * load/store operations for 64 bit registers + * again, declared in tracewrap.h and defined here + * */ +OperandInfo *load_store_reg64(uint32_t reg, uint64_t val, int ls) { + return build_load_store_reg_op(reg, val, sizeof(val), ls); +} +void HELPER(trace_load_reg64)(uint32_t reg, uint64_t val) { load_store_reg64(reg, val, 0); } +void HELPER(trace_store_reg64)(uint32_t reg, uint64_t val) { load_store_reg64(reg, val, 1); } +#endif + +/** + * Load/Store a value from/to a memory region + * + * @param addr is address of memory region + * @param val is value to be stored + * @param len is length (size) in bytes of val + * @param ls if 0 means this is a LOAD operation, otherwise STORE operation + * + * @return OperandInfo + * */ +OperandInfo * load_store_mem(uint64_t addr, int ls, const void* data, size_t data_size) { + // create new memory operand MemOperand * mo = g_new(MemOperand,1); mem_operand__init(mo); - mo->address = addr; + // reg operand? memory operand? OperandInfoSpecific *ois = g_new(OperandInfoSpecific,1); operand_info_specific__init(ois); ois->mem_operand = mo; + // did we just wrote a value or read value? OperandUsage *ou = g_new(OperandUsage,1); operand_usage__init(ou); if (ls == 0) { @@ -98,32 +112,54 @@ OperandInfo * load_store_mem(uint32_t addr, uint32_t val, int ls, int len) { } else { ou->written = 1; } + + // sum up all information OperandInfo *oi = g_new(OperandInfo,1); operand_info__init(oi); - oi->bit_length = len*8; + oi->bit_length = data_size*8; oi->operand_info_specific = ois; oi->operand_usage = ou; - oi->value.len = len; + oi->value.len = data_size; oi->value.data = g_malloc(oi->value.len); - memcpy(oi->value.data, &val, len); + memcpy(oi->value.data, data, data_size); return oi; } -void HELPER(trace_ld)(CPUMIPSState *env, uint32_t val, uint32_t addr) -{ - qemu_log("This was a read 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); +void HELPER(trace_load_mem)(uint32_t addr, uint32_t val, MemOp op) { + qemu_log("LOAD at 0x%lx size: %d data: 0x%lx\n", (unsigned long) addr, memop_size(op), (unsigned long) val); + OperandInfo *oi = load_store_mem(addr, 0, &val, memop_size(op)); + qemu_trace_add_operand(oi, 0x1); +} - OperandInfo *oi = load_store_mem(addr, val, 0, 4); +void HELPER(trace_store_mem)(uint32_t addr, uint32_t val, MemOp op) { + qemu_log("STORE at 0x%lx size: %d data: 0x%lx\n", (unsigned long) addr, memop_size(op), (unsigned long) val); + OperandInfo *oi = load_store_mem(addr, 1, &val, memop_size(op)); + qemu_trace_add_operand(oi, 0x2); +} +void HELPER(trace_load_mem_i64)(uint32_t addr, uint64_t val, MemOp op) { + qemu_log("LOAD at 0x%lx size: %d data: 0x%llx\n", (unsigned long) addr, memop_size(op), (unsigned long long) val); + OperandInfo *oi = load_store_mem(addr, 0, &val, memop_size(op)); qemu_trace_add_operand(oi, 0x1); } -void HELPER(trace_st)(CPUMIPSState *env, uint32_t val, uint32_t addr) -{ - qemu_log("This was a store 0x%x addr:0x%x value:0x%x\n", env->active_tc.PC, addr, val); +void HELPER(trace_store_mem_i64)(uint32_t addr, uint64_t val, MemOp op) { + qemu_log("STORE at 0x%lx size: %d data: 0x%llx\n", (unsigned long) addr, memop_size(op), (unsigned long long) val); + OperandInfo *oi = load_store_mem(addr, 1, &val, memop_size(op)); + qemu_trace_add_operand(oi, 0x2); +} - OperandInfo *oi = load_store_mem(addr, val, 1, 4); +#ifdef TARGET_MIPS64 +void HELPER(trace_load_mem64)(uint64_t addr, uint64_t val, MemOp op) { + qemu_log("LOAD at 0x%llx size: %d data: 0x%llx\n", (unsigned long long) addr, memop_size(op), (unsigned long long) val); + OperandInfo *oi = load_store_mem(addr, 0, &val, memop_size(op)); + qemu_trace_add_operand(oi, 0x1); +} +void HELPER(trace_store_mem64)(uint64_t addr, uint64_t val, MemOp op) { + qemu_log("STORE at 0x%llx size: %d data: 0x%llx\n", (unsigned long long) addr, memop_size(op), (unsigned long long) val); + OperandInfo *oi = load_store_mem(addr, 1, &val, memop_size(op)); qemu_trace_add_operand(oi, 0x2); } +#endif diff --git a/util/async.c b/util/async.c index 6f6717a34b631..2d8f540536985 100644 --- a/util/async.c +++ b/util/async.c @@ -144,12 +144,12 @@ void aio_bh_call(QEMUBH *bh) /* Multiple occurrences of aio_bh_poll cannot be called concurrently. */ int aio_bh_poll(AioContext *ctx) { - BHListSlice slice; + BHListSlice *slice = g_malloc(sizeof(BHListSlice)); BHListSlice *s; int ret = 0; - QSLIST_MOVE_ATOMIC(&slice.bh_list, &ctx->bh_list); - QSIMPLEQ_INSERT_TAIL(&ctx->bh_slice_list, &slice, next); + QSLIST_MOVE_ATOMIC(&slice->bh_list, &ctx->bh_list); + QSIMPLEQ_INSERT_TAIL(&ctx->bh_slice_list, slice, next); while ((s = QSIMPLEQ_FIRST(&ctx->bh_slice_list))) { QEMUBH *bh;