现在的位置: 首页 > 综合 > 正文

qemu internal (1) the code path of memory load emulation

2017年12月20日 ⁄ 综合 ⁄ 共 3897字 ⁄ 字号 评论关闭

qemu internal part 1: the code path of memory load emulation

In qemu, there are two different meanings of target. The first meaning of ‘target’ means the emulated target machine architecture. For example, when emulating mips machine on x86, the
target is mips and host is x86. However, in tcg(tiny code generator), target has a different meaning. It means the generated binary architecture. In the example of emulating mips on x86, in tcg the target means x86 because tcg will generate x86 binary.

This article is based on
qemu
version 0.10.5 and target machine emulated is little endian mips. I will summarize the code path of mips lw instruction emulation in
qemu.

Function decode_opc is used for decoding all the fetched instructions before tcg generating the target binary.

target-mips/translate.c

7566 static void decode_opc (CPUState *env, DisasContext *ctx)

7960     case OPC_LB ... OPC_LWR: /* Load and stores */
7961     case OPC_SB ... OPC_SW:
7962     case OPC_SWR:
7963     case OPC_LL:
7964     case OPC_SC:
7965          gen_ldst(ctx, op, rt, rs, imm);
7966          break;

It will call function gen_ldst which is also in target-mips/translate.c.

target-mips/translate.c

973 static void gen_ldst (DisasContext *ctx, uint32_t opc, int rt,
974                       int base, int16_t offset)

1046     case OPC_LW:
1047         op_ldst_lw(t0, ctx);
1048         gen_store_gpr(t0, rt);
1049         opn = "lw";
1050         break;

Function op_ldst_lw will generate the target binary which fetches the value from the emulated guest memory and gen_store_gpr will store this value to the emulated cpu’s general register rt.Function op_ldst_lw is generated by the macro OP_LD.

target-mips/translate.c

901 #define OP_LD(insn,fname)                                        \
902 static inline void op_ldst_##insn(TCGv t0, DisasContext *ctx)    \
903 {                                                                \
904     tcg_gen_qemu_##fname(t0, t0, ctx->mem_idx);                  \
905 }

910 OP_LD(lw,ld32s);

We can find that op_ldst_lw is a function which calls function tcg_gen_qemu_ld32s. It will output the OPC(INDEX_op_qemu_ld32u) and args to gen_opc_ptr.

tcg/tcg-op.h

1793 static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
1794 {
1795 #if TARGET_LONG_BITS == 32
1796     tcg_gen_op3i_i32(INDEX_op_qemu_ld32u, ret, addr, mem_index);
1797 #else
1798     tcg_gen_op4i_i32(INDEX_op_qemu_ld32u, TCGV_LOW(ret), TCGV_LOW(addr),
1799                      TCGV_HIGH(addr), mem_index);
1800     tcg_gen_sari_i32(TCGV_HIGH(ret), TCGV_LOW(ret), 31);
1801 #endif
1802 }

99 static inline void tcg_gen_op3i_i32(int opc, TCGv_i32 arg1, TCGv_i32 arg2,
100                                     TCGArg arg3)
101 {
102     *gen_opc_ptr++ = opc;
103     *gen_opparam_ptr++ = GET_TCGV_I32(arg1);
104     *gen_opparam_ptr++ = GET_TCGV_I32(arg2);
105     *gen_opparam_ptr++ = arg3;
106 }

The path of generation of target binary code of tcg is as following.

cpu_gen_code->tcg_gen_code->tcg_gen_code_common->tcg_reg_alloc_op->tcg_out_op
tcg/i386/tcg-target.c

856 static inline void tcg_out_op(TCGContext *s, int opc,
857                               const TCGArg *args, const int *const_args)

1041     case INDEX_op_qemu_ld32u:
1042         tcg_out_qemu_ld(s, args, 2);
1043         break;

431 static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
432                             int opc)

508 #if TARGET_LONG_BITS == 32
509     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
510 #else
511     tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
512     tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
513 #endif
514     tcg_out8(s, 0xe8);
515     tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -
516               (tcg_target_long)s->code_ptr - 4);

In line 514, tcg outputs 0xe8 which means a call instruction in x86. It will call the functions in array qemu_ld_helpers. The args to the functions is passed by registers EAX,EDX and ECX.

tcg/i386/tcg-target.c

413 static void *qemu_ld_helpers[4] = {
414     __ldb_mmu,
415     __ldw_mmu,
416     __ldl_mmu,
417     __ldq_mmu,
418 };

These functions __ldb_mmu/__ldw_mmu are defined in softmmu_template.h.

softmmu_tempate.h

DATA_TYPE REGPARM glue(glue(__ld, SUFFIX), MMUSUFFIX)(target_ulong addr,
int mmu_idx)

In sum, function gen_ldst outputs the OPC(INDEX_op_qemu_ld32u) to gen_opc_ptr and tcg_out_op will generates the target binary according to the OPC. In the lw instruction emulation, it will generate the x86 binary calls the functions in softmmu_template.h.

抱歉!评论已关闭.