mirror of https://github.com/xemu-project/xemu.git
Testing and plugin updates:
- fix pauth TCG tests - tweak away rcutorture failures - various Travis updates - relax iotest size check a little - fix for -trace/-D clash - fix cross compile detection for tcg tests - document plugin query lifetime - fix missing break in plugin core - fix some plugin warnings - better progressive instruction decode - avoid trampling vaddr in plugins -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl5VgeQACgkQ+9DbCVqe KkTZxQf9GSTivhKCQuBIHO/g22uEXeoqrVRAvn/43F5p8f+Y23JcO9ej1ScDfyvk ZvYwL39SzCEVakiJnoYw/AR38DQhE5OsRLwvaAUXapPG4QsLlSu1XB9JltZMbM92 yAjfnyH/90OijNrMhjncD2uikVgo37gqygRP8v9ztegoc/U/4QWLqVgqGXvcbcTT A4g0DCfWfxdOl4kVMYRLXODBjYkZCLtflU32Q+VX4Jem/LPDZNw9zbVB0tUC6iTg VDMO//ARK5HeDv1yRuN34wmUPLRVWYvMpjlFk2yLfX6Z/BuMz0VrN6FBptA2P67x Bn4ooyjiGeiJ9sKG5ra1HMbm2nJ+Xg== =ncn4 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-plugins-250220-1' into staging Testing and plugin updates: - fix pauth TCG tests - tweak away rcutorture failures - various Travis updates - relax iotest size check a little - fix for -trace/-D clash - fix cross compile detection for tcg tests - document plugin query lifetime - fix missing break in plugin core - fix some plugin warnings - better progressive instruction decode - avoid trampling vaddr in plugins # gpg: Signature made Tue 25 Feb 2020 20:21:56 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-plugins-250220-1: tests/tcg: take into account expected clashes pauth-4 tests/tcg: fix typo in configure.sh test for v8.3 tcg: save vaddr temp for plugin usage tests/tcg: give debug builds a little bit longer tests/plugins: make howvec clean-up after itself. target/riscv: progressively load the instruction during decode qemu/bitops.h: Add extract8 and extract16 tests/plugin: prevent uninitialized warning plugins/core: add missing break in cb_to_tcg_flags docs/devel: document query handle lifetimes tracing: only allow -trace to override -D if set tests/iotests: be a little more forgiving on the size test travis.yml: single-thread build-tcg stages travis.yml: Fix Travis YAML configuration warnings travis.yml: Test the s390-ccw build, too tests/rcutorture: mild documenting refactor of update thread tests/rcutorture: better document locking of stats tests/rcutorture: update usage hint tests/tcg: include a skip runner for pauth3 with plugins Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
8b6269c8ec
23
.travis.yml
23
.travis.yml
|
@ -1,6 +1,7 @@
|
||||||
# The current Travis default is a VM based 16.04 Xenial on GCE
|
# The current Travis default is a VM based 16.04 Xenial on GCE
|
||||||
# Additional builds with specific requirements for a full VM need to
|
# Additional builds with specific requirements for a full VM need to
|
||||||
# be added as additional matrix: entries later on
|
# be added as additional matrix: entries later on
|
||||||
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
language: c
|
language: c
|
||||||
compiler:
|
compiler:
|
||||||
|
@ -113,7 +114,7 @@ after_script:
|
||||||
- if command -v ccache ; then ccache --show-stats ; fi
|
- if command -v ccache ; then ccache --show-stats ; fi
|
||||||
|
|
||||||
|
|
||||||
matrix:
|
jobs:
|
||||||
include:
|
include:
|
||||||
- name: "GCC static (user)"
|
- name: "GCC static (user)"
|
||||||
env:
|
env:
|
||||||
|
@ -297,8 +298,7 @@ matrix:
|
||||||
- CONFIG="--target-list=x86_64-softmmu"
|
- CONFIG="--target-list=x86_64-softmmu"
|
||||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||||
language: python
|
language: python
|
||||||
python:
|
python: 3.5
|
||||||
- "3.5"
|
|
||||||
|
|
||||||
|
|
||||||
- name: "GCC Python 3.6 (x86_64-softmmu)"
|
- name: "GCC Python 3.6 (x86_64-softmmu)"
|
||||||
|
@ -306,8 +306,7 @@ matrix:
|
||||||
- CONFIG="--target-list=x86_64-softmmu"
|
- CONFIG="--target-list=x86_64-softmmu"
|
||||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-default"
|
||||||
language: python
|
language: python
|
||||||
python:
|
python: 3.6
|
||||||
- "3.6"
|
|
||||||
|
|
||||||
|
|
||||||
# Acceptance (Functional) tests
|
# Acceptance (Functional) tests
|
||||||
|
@ -401,7 +400,7 @@ matrix:
|
||||||
- name: "GCC check-tcg (some-softmmu)"
|
- name: "GCC check-tcg (some-softmmu)"
|
||||||
env:
|
env:
|
||||||
- CONFIG="--enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
- CONFIG="--enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
||||||
- TEST_BUILD_CMD="make -j${JOBS} build-tcg"
|
- TEST_BUILD_CMD="make build-tcg"
|
||||||
- TEST_CMD="make check-tcg"
|
- TEST_CMD="make check-tcg"
|
||||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||||
|
|
||||||
|
@ -410,7 +409,7 @@ matrix:
|
||||||
- name: "GCC plugins check-tcg (some-softmmu)"
|
- name: "GCC plugins check-tcg (some-softmmu)"
|
||||||
env:
|
env:
|
||||||
- CONFIG="--enable-plugins --enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
- CONFIG="--enable-plugins --enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu"
|
||||||
- TEST_BUILD_CMD="make -j${JOBS} build-tcg"
|
- TEST_BUILD_CMD="make build-tcg"
|
||||||
- TEST_CMD="make check-tcg"
|
- TEST_CMD="make check-tcg"
|
||||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||||
|
|
||||||
|
@ -509,6 +508,16 @@ matrix:
|
||||||
env:
|
env:
|
||||||
- TEST_CMD="make check check-tcg V=1"
|
- TEST_CMD="make check check-tcg V=1"
|
||||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||||
|
script:
|
||||||
|
- ( cd ${SRC_DIR} ; git submodule update --init roms/SLOF )
|
||||||
|
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
|
||||||
|
- |
|
||||||
|
if [ "$BUILD_RC" -eq 0 ] ; then
|
||||||
|
mv pc-bios/s390-ccw/*.img pc-bios/ ;
|
||||||
|
${TEST_CMD} ;
|
||||||
|
else
|
||||||
|
$(exit $BUILD_RC);
|
||||||
|
fi
|
||||||
|
|
||||||
# Release builds
|
# Release builds
|
||||||
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
||||||
|
|
|
@ -51,8 +51,17 @@ about how QEMU's translation works to the plugins. While there are
|
||||||
conceptions such as translation time and translation blocks the
|
conceptions such as translation time and translation blocks the
|
||||||
details are opaque to plugins. The plugin is able to query select
|
details are opaque to plugins. The plugin is able to query select
|
||||||
details of instructions and system configuration only through the
|
details of instructions and system configuration only through the
|
||||||
exported *qemu_plugin* functions. The types used to describe
|
exported *qemu_plugin* functions.
|
||||||
instructions and events are opaque to the plugins themselves.
|
|
||||||
|
Query Handle Lifetime
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Each callback provides an opaque anonymous information handle which
|
||||||
|
can usually be further queried to find out information about a
|
||||||
|
translation, instruction or operation. The handles themselves are only
|
||||||
|
valid during the lifetime of the callback so it is important that any
|
||||||
|
information that is needed is extracted during the callback and saved
|
||||||
|
by the plugin.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
|
@ -301,6 +301,44 @@ static inline uint32_t extract32(uint32_t value, int start, int length)
|
||||||
return (value >> start) & (~0U >> (32 - length));
|
return (value >> start) & (~0U >> (32 - length));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract8:
|
||||||
|
* @value: the value to extract the bit field from
|
||||||
|
* @start: the lowest bit in the bit field (numbered from 0)
|
||||||
|
* @length: the length of the bit field
|
||||||
|
*
|
||||||
|
* Extract from the 8 bit input @value the bit field specified by the
|
||||||
|
* @start and @length parameters, and return it. The bit field must
|
||||||
|
* lie entirely within the 8 bit word. It is valid to request that
|
||||||
|
* all 8 bits are returned (ie @length 8 and @start 0).
|
||||||
|
*
|
||||||
|
* Returns: the value of the bit field extracted from the input value.
|
||||||
|
*/
|
||||||
|
static inline uint8_t extract8(uint8_t value, int start, int length)
|
||||||
|
{
|
||||||
|
assert(start >= 0 && length > 0 && length <= 8 - start);
|
||||||
|
return extract32(value, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract16:
|
||||||
|
* @value: the value to extract the bit field from
|
||||||
|
* @start: the lowest bit in the bit field (numbered from 0)
|
||||||
|
* @length: the length of the bit field
|
||||||
|
*
|
||||||
|
* Extract from the 16 bit input @value the bit field specified by the
|
||||||
|
* @start and @length parameters, and return it. The bit field must
|
||||||
|
* lie entirely within the 16 bit word. It is valid to request that
|
||||||
|
* all 16 bits are returned (ie @length 16 and @start 0).
|
||||||
|
*
|
||||||
|
* Returns: the value of the bit field extracted from the input value.
|
||||||
|
*/
|
||||||
|
static inline uint16_t extract16(uint16_t value, int start, int length)
|
||||||
|
{
|
||||||
|
assert(start >= 0 && length > 0 && length <= 16 - start);
|
||||||
|
return extract32(value, start, length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* extract64:
|
* extract64:
|
||||||
* @value: the value to extract the bit field from
|
* @value: the value to extract the bit field from
|
||||||
|
|
|
@ -286,6 +286,7 @@ static inline uint32_t cb_to_tcg_flags(enum qemu_plugin_cb_flags flags)
|
||||||
switch (flags) {
|
switch (flags) {
|
||||||
case QEMU_PLUGIN_CB_RW_REGS:
|
case QEMU_PLUGIN_CB_RW_REGS:
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
break;
|
||||||
case QEMU_PLUGIN_CB_R_REGS:
|
case QEMU_PLUGIN_CB_R_REGS:
|
||||||
ret = TCG_CALL_NO_WG;
|
ret = TCG_CALL_NO_WG;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -344,8 +344,8 @@ enum {
|
||||||
#define GET_C_LW_IMM(inst) ((extract32(inst, 6, 1) << 2) \
|
#define GET_C_LW_IMM(inst) ((extract32(inst, 6, 1) << 2) \
|
||||||
| (extract32(inst, 10, 3) << 3) \
|
| (extract32(inst, 10, 3) << 3) \
|
||||||
| (extract32(inst, 5, 1) << 6))
|
| (extract32(inst, 5, 1) << 6))
|
||||||
#define GET_C_LD_IMM(inst) ((extract32(inst, 10, 3) << 3) \
|
#define GET_C_LD_IMM(inst) ((extract16(inst, 10, 3) << 3) \
|
||||||
| (extract32(inst, 5, 2) << 6))
|
| (extract16(inst, 5, 2) << 6))
|
||||||
#define GET_C_J_IMM(inst) ((extract32(inst, 3, 3) << 1) \
|
#define GET_C_J_IMM(inst) ((extract32(inst, 3, 3) << 1) \
|
||||||
| (extract32(inst, 11, 1) << 4) \
|
| (extract32(inst, 11, 1) << 4) \
|
||||||
| (extract32(inst, 2, 1) << 5) \
|
| (extract32(inst, 2, 1) << 5) \
|
||||||
|
@ -363,7 +363,7 @@ enum {
|
||||||
#define GET_C_RD(inst) GET_RD(inst)
|
#define GET_C_RD(inst) GET_RD(inst)
|
||||||
#define GET_C_RS1(inst) GET_RD(inst)
|
#define GET_C_RS1(inst) GET_RD(inst)
|
||||||
#define GET_C_RS2(inst) extract32(inst, 2, 5)
|
#define GET_C_RS2(inst) extract32(inst, 2, 5)
|
||||||
#define GET_C_RS1S(inst) (8 + extract32(inst, 7, 3))
|
#define GET_C_RS1S(inst) (8 + extract16(inst, 7, 3))
|
||||||
#define GET_C_RS2S(inst) (8 + extract32(inst, 2, 3))
|
#define GET_C_RS2S(inst) (8 + extract16(inst, 2, 3))
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -44,7 +44,6 @@ typedef struct DisasContext {
|
||||||
/* pc_succ_insn points to the instruction following base.pc_next */
|
/* pc_succ_insn points to the instruction following base.pc_next */
|
||||||
target_ulong pc_succ_insn;
|
target_ulong pc_succ_insn;
|
||||||
target_ulong priv_ver;
|
target_ulong priv_ver;
|
||||||
uint32_t opcode;
|
|
||||||
uint32_t mstatus_fs;
|
uint32_t mstatus_fs;
|
||||||
uint32_t misa;
|
uint32_t misa;
|
||||||
uint32_t mem_idx;
|
uint32_t mem_idx;
|
||||||
|
@ -492,45 +491,45 @@ static void gen_set_rm(DisasContext *ctx, int rm)
|
||||||
tcg_temp_free_i32(t0);
|
tcg_temp_free_i32(t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64C0(DisasContext *ctx)
|
static void decode_RV32_64C0(DisasContext *ctx, uint16_t opcode)
|
||||||
{
|
{
|
||||||
uint8_t funct3 = extract32(ctx->opcode, 13, 3);
|
uint8_t funct3 = extract16(opcode, 13, 3);
|
||||||
uint8_t rd_rs2 = GET_C_RS2S(ctx->opcode);
|
uint8_t rd_rs2 = GET_C_RS2S(opcode);
|
||||||
uint8_t rs1s = GET_C_RS1S(ctx->opcode);
|
uint8_t rs1s = GET_C_RS1S(opcode);
|
||||||
|
|
||||||
switch (funct3) {
|
switch (funct3) {
|
||||||
case 3:
|
case 3:
|
||||||
#if defined(TARGET_RISCV64)
|
#if defined(TARGET_RISCV64)
|
||||||
/* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/
|
/* C.LD(RV64/128) -> ld rd', offset[7:3](rs1')*/
|
||||||
gen_load_c(ctx, OPC_RISC_LD, rd_rs2, rs1s,
|
gen_load_c(ctx, OPC_RISC_LD, rd_rs2, rs1s,
|
||||||
GET_C_LD_IMM(ctx->opcode));
|
GET_C_LD_IMM(opcode));
|
||||||
#else
|
#else
|
||||||
/* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/
|
/* C.FLW (RV32) -> flw rd', offset[6:2](rs1')*/
|
||||||
gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s,
|
gen_fp_load(ctx, OPC_RISC_FLW, rd_rs2, rs1s,
|
||||||
GET_C_LW_IMM(ctx->opcode));
|
GET_C_LW_IMM(opcode));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
case 7:
|
case 7:
|
||||||
#if defined(TARGET_RISCV64)
|
#if defined(TARGET_RISCV64)
|
||||||
/* C.SD (RV64/128) -> sd rs2', offset[7:3](rs1')*/
|
/* C.SD (RV64/128) -> sd rs2', offset[7:3](rs1')*/
|
||||||
gen_store_c(ctx, OPC_RISC_SD, rs1s, rd_rs2,
|
gen_store_c(ctx, OPC_RISC_SD, rs1s, rd_rs2,
|
||||||
GET_C_LD_IMM(ctx->opcode));
|
GET_C_LD_IMM(opcode));
|
||||||
#else
|
#else
|
||||||
/* C.FSW (RV32) -> fsw rs2', offset[6:2](rs1')*/
|
/* C.FSW (RV32) -> fsw rs2', offset[6:2](rs1')*/
|
||||||
gen_fp_store(ctx, OPC_RISC_FSW, rs1s, rd_rs2,
|
gen_fp_store(ctx, OPC_RISC_FSW, rs1s, rd_rs2,
|
||||||
GET_C_LW_IMM(ctx->opcode));
|
GET_C_LW_IMM(opcode));
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decode_RV32_64C(DisasContext *ctx)
|
static void decode_RV32_64C(DisasContext *ctx, uint16_t opcode)
|
||||||
{
|
{
|
||||||
uint8_t op = extract32(ctx->opcode, 0, 2);
|
uint8_t op = extract16(opcode, 0, 2);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case 0:
|
case 0:
|
||||||
decode_RV32_64C0(ctx);
|
decode_RV32_64C0(ctx, opcode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -709,22 +708,25 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
|
||||||
/* Include the auto-generated decoder for 16 bit insn */
|
/* Include the auto-generated decoder for 16 bit insn */
|
||||||
#include "decode_insn16.inc.c"
|
#include "decode_insn16.inc.c"
|
||||||
|
|
||||||
static void decode_opc(DisasContext *ctx)
|
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
|
||||||
{
|
{
|
||||||
/* check for compressed insn */
|
/* check for compressed insn */
|
||||||
if (extract32(ctx->opcode, 0, 2) != 3) {
|
if (extract16(opcode, 0, 2) != 3) {
|
||||||
if (!has_ext(ctx, RVC)) {
|
if (!has_ext(ctx, RVC)) {
|
||||||
gen_exception_illegal(ctx);
|
gen_exception_illegal(ctx);
|
||||||
} else {
|
} else {
|
||||||
ctx->pc_succ_insn = ctx->base.pc_next + 2;
|
ctx->pc_succ_insn = ctx->base.pc_next + 2;
|
||||||
if (!decode_insn16(ctx, ctx->opcode)) {
|
if (!decode_insn16(ctx, opcode)) {
|
||||||
/* fall back to old decoder */
|
/* fall back to old decoder */
|
||||||
decode_RV32_64C(ctx);
|
decode_RV32_64C(ctx, opcode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
uint32_t opcode32 = opcode;
|
||||||
|
opcode32 = deposit32(opcode32, 16, 16,
|
||||||
|
translator_lduw(env, ctx->base.pc_next + 2));
|
||||||
ctx->pc_succ_insn = ctx->base.pc_next + 4;
|
ctx->pc_succ_insn = ctx->base.pc_next + 4;
|
||||||
if (!decode_insn32(ctx, ctx->opcode)) {
|
if (!decode_insn32(ctx, opcode32)) {
|
||||||
gen_exception_illegal(ctx);
|
gen_exception_illegal(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -776,9 +778,9 @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
|
||||||
{
|
{
|
||||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||||
CPURISCVState *env = cpu->env_ptr;
|
CPURISCVState *env = cpu->env_ptr;
|
||||||
|
uint16_t opcode16 = translator_lduw(env, ctx->base.pc_next);
|
||||||
|
|
||||||
ctx->opcode = translator_ldl(env, ctx->base.pc_next);
|
decode_opc(env, ctx, opcode16);
|
||||||
decode_opc(ctx);
|
|
||||||
ctx->base.pc_next = ctx->pc_succ_insn;
|
ctx->base.pc_next = ctx->pc_succ_insn;
|
||||||
|
|
||||||
if (ctx->base.is_jmp == DISAS_NEXT) {
|
if (ctx->base.is_jmp == DISAS_NEXT) {
|
||||||
|
|
23
tcg/tcg-op.c
23
tcg/tcg-op.c
|
@ -2794,13 +2794,26 @@ static void tcg_gen_req_mo(TCGBar type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline TCGv plugin_prep_mem_callbacks(TCGv vaddr)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_PLUGIN
|
||||||
|
if (tcg_ctx->plugin_insn != NULL) {
|
||||||
|
/* Save a copy of the vaddr for use after a load. */
|
||||||
|
TCGv temp = tcg_temp_new();
|
||||||
|
tcg_gen_mov_tl(temp, vaddr);
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return vaddr;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
|
static inline void plugin_gen_mem_callbacks(TCGv vaddr, uint16_t info)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_PLUGIN
|
#ifdef CONFIG_PLUGIN
|
||||||
if (tcg_ctx->plugin_insn == NULL) {
|
if (tcg_ctx->plugin_insn != NULL) {
|
||||||
return;
|
plugin_gen_empty_mem_callback(vaddr, info);
|
||||||
|
tcg_temp_free(vaddr);
|
||||||
}
|
}
|
||||||
plugin_gen_empty_mem_callback(vaddr, info);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2822,6 +2835,7 @@ void tcg_gen_qemu_ld_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = plugin_prep_mem_callbacks(addr);
|
||||||
gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
|
gen_ldst_i32(INDEX_op_qemu_ld_i32, val, addr, memop, idx);
|
||||||
plugin_gen_mem_callbacks(addr, info);
|
plugin_gen_mem_callbacks(addr, info);
|
||||||
|
|
||||||
|
@ -2868,6 +2882,7 @@ void tcg_gen_qemu_st_i32(TCGv_i32 val, TCGv addr, TCGArg idx, MemOp memop)
|
||||||
memop &= ~MO_BSWAP;
|
memop &= ~MO_BSWAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = plugin_prep_mem_callbacks(addr);
|
||||||
gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
|
gen_ldst_i32(INDEX_op_qemu_st_i32, val, addr, memop, idx);
|
||||||
plugin_gen_mem_callbacks(addr, info);
|
plugin_gen_mem_callbacks(addr, info);
|
||||||
|
|
||||||
|
@ -2905,6 +2920,7 @@ void tcg_gen_qemu_ld_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = plugin_prep_mem_callbacks(addr);
|
||||||
gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
|
gen_ldst_i64(INDEX_op_qemu_ld_i64, val, addr, memop, idx);
|
||||||
plugin_gen_mem_callbacks(addr, info);
|
plugin_gen_mem_callbacks(addr, info);
|
||||||
|
|
||||||
|
@ -2967,6 +2983,7 @@ void tcg_gen_qemu_st_i64(TCGv_i64 val, TCGv addr, TCGArg idx, MemOp memop)
|
||||||
memop &= ~MO_BSWAP;
|
memop &= ~MO_BSWAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addr = plugin_prep_mem_callbacks(addr);
|
||||||
gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
|
gen_ldst_i64(INDEX_op_qemu_st_i64, val, addr, memop, idx);
|
||||||
plugin_gen_mem_callbacks(addr, info);
|
plugin_gen_mem_callbacks(addr, info);
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,9 @@ static bool do_inline;
|
||||||
|
|
||||||
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
||||||
{
|
{
|
||||||
g_autofree gchar *out;
|
g_autofree gchar *out = g_strdup_printf(
|
||||||
out = g_strdup_printf("bb's: %" PRIu64", insns: %" PRIu64 "\n",
|
"bb's: %" PRIu64", insns: %" PRIu64 "\n",
|
||||||
bb_count, insn_count);
|
bb_count, insn_count);
|
||||||
qemu_plugin_outs(out);
|
qemu_plugin_outs(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,6 +163,13 @@ static gint cmp_exec_count(gconstpointer a, gconstpointer b)
|
||||||
return ea->count > eb->count ? -1 : 1;
|
return ea->count > eb->count ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void free_record(gpointer data)
|
||||||
|
{
|
||||||
|
InsnExecCount *rec = (InsnExecCount *) data;
|
||||||
|
g_free(rec->insn);
|
||||||
|
g_free(rec);
|
||||||
|
}
|
||||||
|
|
||||||
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
||||||
{
|
{
|
||||||
g_autoptr(GString) report = g_string_new("Instruction Classes:\n");
|
g_autoptr(GString) report = g_string_new("Instruction Classes:\n");
|
||||||
|
@ -195,30 +202,31 @@ static void plugin_exit(qemu_plugin_id_t id, void *p)
|
||||||
|
|
||||||
counts = g_hash_table_get_values(insns);
|
counts = g_hash_table_get_values(insns);
|
||||||
if (counts && g_list_next(counts)) {
|
if (counts && g_list_next(counts)) {
|
||||||
GList *it;
|
|
||||||
|
|
||||||
g_string_append_printf(report,"Individual Instructions:\n");
|
g_string_append_printf(report,"Individual Instructions:\n");
|
||||||
|
counts = g_list_sort(counts, cmp_exec_count);
|
||||||
|
|
||||||
it = g_list_sort(counts, cmp_exec_count);
|
for (i = 0; i < limit && g_list_next(counts);
|
||||||
|
i++, counts = g_list_next(counts)) {
|
||||||
for (i = 0; i < limit && it->next; i++, it = it->next) {
|
InsnExecCount *rec = (InsnExecCount *) counts->data;
|
||||||
InsnExecCount *rec = (InsnExecCount *) it->data;
|
g_string_append_printf(report,
|
||||||
g_string_append_printf(report, "Instr: %-24s\t(%ld hits)\t(op=%#08x/%s)\n",
|
"Instr: %-24s\t(%ld hits)\t(op=%#08x/%s)\n",
|
||||||
rec->insn,
|
rec->insn,
|
||||||
rec->count,
|
rec->count,
|
||||||
rec->opcode,
|
rec->opcode,
|
||||||
rec->class ?
|
rec->class ?
|
||||||
rec->class->class : "un-categorised");
|
rec->class->class : "un-categorised");
|
||||||
}
|
}
|
||||||
g_list_free(it);
|
g_list_free(counts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
g_hash_table_destroy(insns);
|
||||||
|
|
||||||
qemu_plugin_outs(report->str);
|
qemu_plugin_outs(report->str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void plugin_init(void)
|
static void plugin_init(void)
|
||||||
{
|
{
|
||||||
insns = g_hash_table_new(NULL, g_direct_equal);
|
insns = g_hash_table_new_full(NULL, g_direct_equal, NULL, &free_record);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata)
|
static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata)
|
||||||
|
|
|
@ -44,8 +44,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
|
||||||
|
|
||||||
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
||||||
{
|
{
|
||||||
g_autofree gchar *out;
|
g_autofree gchar *out = g_strdup_printf("insns: %" PRIu64 "\n", insn_count);
|
||||||
out = g_strdup_printf("insns: %" PRIu64 "\n", insn_count);
|
|
||||||
qemu_plugin_outs(out);
|
qemu_plugin_outs(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -125,9 +125,9 @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\
|
||||||
sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
|
sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" |
|
||||||
sed -n '/"actual-size":/ s/[^0-9]//gp')
|
sed -n '/"actual-size":/ s/[^0-9]//gp')
|
||||||
|
|
||||||
if [ $sizeA -le $sizeB ]
|
if [ $sizeA -lt $sizeB ]
|
||||||
then
|
then
|
||||||
echo "Compression ERROR"
|
echo "Compression ERROR ($sizeA < $sizeB)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
$QEMU_IMG check --output=json "$TEST_IMG" |
|
$QEMU_IMG check --output=json "$TEST_IMG" |
|
||||||
|
|
|
@ -65,8 +65,6 @@
|
||||||
#include "qemu/rcu.h"
|
#include "qemu/rcu.h"
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
|
|
||||||
long long n_reads = 0LL;
|
|
||||||
long n_updates = 0L;
|
|
||||||
int nthreadsrunning;
|
int nthreadsrunning;
|
||||||
|
|
||||||
#define GOFLAG_INIT 0
|
#define GOFLAG_INIT 0
|
||||||
|
@ -78,11 +76,20 @@ static volatile int goflag = GOFLAG_INIT;
|
||||||
#define RCU_READ_RUN 1000
|
#define RCU_READ_RUN 1000
|
||||||
|
|
||||||
#define NR_THREADS 100
|
#define NR_THREADS 100
|
||||||
static QemuMutex counts_mutex;
|
|
||||||
static QemuThread threads[NR_THREADS];
|
static QemuThread threads[NR_THREADS];
|
||||||
static struct rcu_reader_data *data[NR_THREADS];
|
static struct rcu_reader_data *data[NR_THREADS];
|
||||||
static int n_threads;
|
static int n_threads;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Statistical counts
|
||||||
|
*
|
||||||
|
* These are the sum of local counters at the end of a run.
|
||||||
|
* Updates are protected by a mutex.
|
||||||
|
*/
|
||||||
|
static QemuMutex counts_mutex;
|
||||||
|
long long n_reads = 0LL;
|
||||||
|
long n_updates = 0L;
|
||||||
|
|
||||||
static void create_thread(void *(*func)(void *))
|
static void create_thread(void *(*func)(void *))
|
||||||
{
|
{
|
||||||
if (n_threads >= NR_THREADS) {
|
if (n_threads >= NR_THREADS) {
|
||||||
|
@ -223,15 +230,15 @@ static void uperftest(int nupdaters, int duration)
|
||||||
#define RCU_STRESS_PIPE_LEN 10
|
#define RCU_STRESS_PIPE_LEN 10
|
||||||
|
|
||||||
struct rcu_stress {
|
struct rcu_stress {
|
||||||
int pipe_count;
|
int age; /* how many update cycles while not rcu_stress_current */
|
||||||
int mbtest;
|
int mbtest;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0 } };
|
struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0 } };
|
||||||
struct rcu_stress *rcu_stress_current;
|
struct rcu_stress *rcu_stress_current;
|
||||||
int rcu_stress_idx;
|
|
||||||
|
|
||||||
int n_mberror;
|
int n_mberror;
|
||||||
|
|
||||||
|
/* Updates protected by counts_mutex */
|
||||||
long long rcu_stress_count[RCU_STRESS_PIPE_LEN + 1];
|
long long rcu_stress_count[RCU_STRESS_PIPE_LEN + 1];
|
||||||
|
|
||||||
|
|
||||||
|
@ -253,7 +260,7 @@ static void *rcu_read_stress_test(void *arg)
|
||||||
while (goflag == GOFLAG_RUN) {
|
while (goflag == GOFLAG_RUN) {
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
p = atomic_rcu_read(&rcu_stress_current);
|
p = atomic_rcu_read(&rcu_stress_current);
|
||||||
if (p->mbtest == 0) {
|
if (atomic_read(&p->mbtest) == 0) {
|
||||||
n_mberror++;
|
n_mberror++;
|
||||||
}
|
}
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
|
@ -261,7 +268,7 @@ static void *rcu_read_stress_test(void *arg)
|
||||||
garbage++;
|
garbage++;
|
||||||
}
|
}
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
pc = p->pipe_count;
|
pc = atomic_read(&p->age);
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) {
|
if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) {
|
||||||
pc = RCU_STRESS_PIPE_LEN;
|
pc = RCU_STRESS_PIPE_LEN;
|
||||||
|
@ -280,32 +287,52 @@ static void *rcu_read_stress_test(void *arg)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Stress Test Updater
|
||||||
|
*
|
||||||
|
* The updater cycles around updating rcu_stress_current to point at
|
||||||
|
* one of the rcu_stress_array_entries and resets it's age. It
|
||||||
|
* then increments the age of all the other entries. The age
|
||||||
|
* will be read under an rcu_read_lock() and distribution of values
|
||||||
|
* calculated. The final result gives an indication of how many
|
||||||
|
* previously current rcu_stress entries are in flight until the RCU
|
||||||
|
* cycle complete.
|
||||||
|
*/
|
||||||
static void *rcu_update_stress_test(void *arg)
|
static void *rcu_update_stress_test(void *arg)
|
||||||
{
|
{
|
||||||
int i;
|
int i, rcu_stress_idx = 0;
|
||||||
struct rcu_stress *p;
|
struct rcu_stress *cp = atomic_read(&rcu_stress_current);
|
||||||
|
|
||||||
rcu_register_thread();
|
rcu_register_thread();
|
||||||
|
|
||||||
*(struct rcu_reader_data **)arg = &rcu_reader;
|
*(struct rcu_reader_data **)arg = &rcu_reader;
|
||||||
|
|
||||||
while (goflag == GOFLAG_INIT) {
|
while (goflag == GOFLAG_INIT) {
|
||||||
g_usleep(1000);
|
g_usleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (goflag == GOFLAG_RUN) {
|
while (goflag == GOFLAG_RUN) {
|
||||||
i = rcu_stress_idx + 1;
|
struct rcu_stress *p;
|
||||||
if (i >= RCU_STRESS_PIPE_LEN) {
|
rcu_stress_idx++;
|
||||||
i = 0;
|
if (rcu_stress_idx >= RCU_STRESS_PIPE_LEN) {
|
||||||
|
rcu_stress_idx = 0;
|
||||||
}
|
}
|
||||||
p = &rcu_stress_array[i];
|
p = &rcu_stress_array[rcu_stress_idx];
|
||||||
p->mbtest = 0;
|
/* catching up with ourselves would be a bug */
|
||||||
|
assert(p != cp);
|
||||||
|
atomic_set(&p->mbtest, 0);
|
||||||
smp_mb();
|
smp_mb();
|
||||||
p->pipe_count = 0;
|
atomic_set(&p->age, 0);
|
||||||
p->mbtest = 1;
|
atomic_set(&p->mbtest, 1);
|
||||||
atomic_rcu_set(&rcu_stress_current, p);
|
atomic_rcu_set(&rcu_stress_current, p);
|
||||||
rcu_stress_idx = i;
|
cp = p;
|
||||||
|
/*
|
||||||
|
* New RCU structure is now live, update pipe counts on old
|
||||||
|
* ones.
|
||||||
|
*/
|
||||||
for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) {
|
for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) {
|
||||||
if (i != rcu_stress_idx) {
|
if (i != rcu_stress_idx) {
|
||||||
rcu_stress_array[i].pipe_count++;
|
atomic_set(&rcu_stress_array[i].age,
|
||||||
|
rcu_stress_array[i].age + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
synchronize_rcu();
|
synchronize_rcu();
|
||||||
|
@ -338,7 +365,7 @@ static void stresstest(int nreaders, int duration)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
rcu_stress_current = &rcu_stress_array[0];
|
rcu_stress_current = &rcu_stress_array[0];
|
||||||
rcu_stress_current->pipe_count = 0;
|
rcu_stress_current->age = 0;
|
||||||
rcu_stress_current->mbtest = 1;
|
rcu_stress_current->mbtest = 1;
|
||||||
for (i = 0; i < nreaders; i++) {
|
for (i = 0; i < nreaders; i++) {
|
||||||
create_thread(rcu_read_stress_test);
|
create_thread(rcu_read_stress_test);
|
||||||
|
@ -368,7 +395,7 @@ static void gtest_stress(int nreaders, int duration)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
rcu_stress_current = &rcu_stress_array[0];
|
rcu_stress_current = &rcu_stress_array[0];
|
||||||
rcu_stress_current->pipe_count = 0;
|
rcu_stress_current->age = 0;
|
||||||
rcu_stress_current->mbtest = 1;
|
rcu_stress_current->mbtest = 1;
|
||||||
for (i = 0; i < nreaders; i++) {
|
for (i = 0; i < nreaders; i++) {
|
||||||
create_thread(rcu_read_stress_test);
|
create_thread(rcu_read_stress_test);
|
||||||
|
@ -413,7 +440,8 @@ static void gtest_stress_10_5(void)
|
||||||
|
|
||||||
static void usage(int argc, char *argv[])
|
static void usage(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: %s [nreaders [ perf | stress ] ]\n", argv[0]);
|
fprintf(stderr, "Usage: %s [nreaders [ [r|u]perf | stress [duration]]\n",
|
||||||
|
argv[0]);
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ QEMU_OPTS=
|
||||||
|
|
||||||
# If TCG debugging is enabled things are a lot slower
|
# If TCG debugging is enabled things are a lot slower
|
||||||
ifeq ($(CONFIG_DEBUG_TCG),y)
|
ifeq ($(CONFIG_DEBUG_TCG),y)
|
||||||
TIMEOUT=45
|
TIMEOUT=60
|
||||||
else
|
else
|
||||||
TIMEOUT=15
|
TIMEOUT=15
|
||||||
endif
|
endif
|
||||||
|
@ -137,7 +137,7 @@ PLUGINS=$(notdir $(wildcard $(PLUGIN_DIR)/*.so))
|
||||||
$(foreach p,$(PLUGINS), \
|
$(foreach p,$(PLUGINS), \
|
||||||
$(foreach t,$(TESTS),\
|
$(foreach t,$(TESTS),\
|
||||||
$(eval run-plugin-$(t)-with-$(p): $t $p) \
|
$(eval run-plugin-$(t)-with-$(p): $t $p) \
|
||||||
$(eval run-plugin-$(t)-with-$(p): TIMEOUT=30) \
|
$(eval run-plugin-$(t)-with-$(p): TIMEOUT=60) \
|
||||||
$(eval RUN_TESTS+=run-plugin-$(t)-with-$(p))))
|
$(eval RUN_TESTS+=run-plugin-$(t)-with-$(p))))
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -70,4 +70,6 @@ pauth-3:
|
||||||
$(call skip-test, "BUILD of $@", "missing compiler support")
|
$(call skip-test, "BUILD of $@", "missing compiler support")
|
||||||
run-pauth-3:
|
run-pauth-3:
|
||||||
$(call skip-test, "RUN of pauth-3", "not built")
|
$(call skip-test, "RUN of pauth-3", "not built")
|
||||||
|
run-plugin-pauth-3-with-%:
|
||||||
|
$(call skip-test, "RUN of pauth-3 ($*)", "not built")
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -1,25 +1,45 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define TESTS 1000
|
||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
uintptr_t x, y;
|
int i, count = 0;
|
||||||
|
float perc;
|
||||||
|
void *base = malloc(TESTS);
|
||||||
|
|
||||||
asm("mov %0, lr\n\t"
|
for (i = 0; i < TESTS; i++) {
|
||||||
"pacia %0, sp\n\t" /* sigill if pauth not supported */
|
uintptr_t in, x, y;
|
||||||
"eor %0, %0, #4\n\t" /* corrupt single bit */
|
|
||||||
"mov %1, %0\n\t"
|
|
||||||
"autia %1, sp\n\t" /* validate corrupted pointer */
|
|
||||||
"xpaci %0\n\t" /* strip pac from corrupted pointer */
|
|
||||||
: "=r"(x), "=r"(y));
|
|
||||||
|
|
||||||
/*
|
in = i + (uintptr_t) base;
|
||||||
* Once stripped, the corrupted pointer is of the form 0x0000...wxyz.
|
|
||||||
* We expect the autia to indicate failure, producing a pointer of the
|
asm("mov %0, %[in]\n\t"
|
||||||
* form 0x000e....wxyz. Use xpaci and != for the test, rather than
|
"pacia %0, sp\n\t" /* sigill if pauth not supported */
|
||||||
* extracting explicit bits from the top, because the location of the
|
"eor %0, %0, #4\n\t" /* corrupt single bit */
|
||||||
* error code "e" depends on the configuration of virtual memory.
|
"mov %1, %0\n\t"
|
||||||
*/
|
"autia %1, sp\n\t" /* validate corrupted pointer */
|
||||||
assert(x != y);
|
"xpaci %0\n\t" /* strip pac from corrupted pointer */
|
||||||
return 0;
|
: /* out */ "=r"(x), "=r"(y)
|
||||||
|
: /* in */ [in] "r" (in)
|
||||||
|
: /* clobbers */);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Once stripped, the corrupted pointer is of the form 0x0000...wxyz.
|
||||||
|
* We expect the autia to indicate failure, producing a pointer of the
|
||||||
|
* form 0x000e....wxyz. Use xpaci and != for the test, rather than
|
||||||
|
* extracting explicit bits from the top, because the location of the
|
||||||
|
* error code "e" depends on the configuration of virtual memory.
|
||||||
|
*/
|
||||||
|
if (x != y) {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
perc = (float) count / (float) TESTS;
|
||||||
|
printf("Checks Passed: %0.2f%%", perc * 100.0);
|
||||||
|
assert(perc > 0.95);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ for target in $target_list; do
|
||||||
echo "CROSS_CC_HAS_SVE=y" >> $config_target_mak
|
echo "CROSS_CC_HAS_SVE=y" >> $config_target_mak
|
||||||
fi
|
fi
|
||||||
if do_compiler "$target_compiler" $target_compiler_cflags \
|
if do_compiler "$target_compiler" $target_compiler_cflags \
|
||||||
-march=-march=armv8.3-a -o $TMPE $TMPC; then
|
-march=armv8.3-a -o $TMPE $TMPC; then
|
||||||
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
|
echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
|
|
|
@ -226,10 +226,15 @@ void trace_init_file(const char *file)
|
||||||
#ifdef CONFIG_TRACE_SIMPLE
|
#ifdef CONFIG_TRACE_SIMPLE
|
||||||
st_set_trace_file(file);
|
st_set_trace_file(file);
|
||||||
#elif defined CONFIG_TRACE_LOG
|
#elif defined CONFIG_TRACE_LOG
|
||||||
/* If both the simple and the log backends are enabled, "--trace file"
|
/*
|
||||||
* only applies to the simple backend; use "-D" for the log backend.
|
* If both the simple and the log backends are enabled, "--trace file"
|
||||||
|
* only applies to the simple backend; use "-D" for the log
|
||||||
|
* backend. However we should only override -D if we actually have
|
||||||
|
* something to override it with.
|
||||||
*/
|
*/
|
||||||
qemu_set_log_filename(file, &error_fatal);
|
if (file) {
|
||||||
|
qemu_set_log_filename(file, &error_fatal);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
if (file) {
|
if (file) {
|
||||||
fprintf(stderr, "error: --trace file=...: "
|
fprintf(stderr, "error: --trace file=...: "
|
||||||
|
|
Loading…
Reference in New Issue