diff options
-rw-r--r-- | linux-user/hexagon/signal.c | 17 | ||||
-rw-r--r-- | scripts/meson-buildoptions.sh | 18 | ||||
-rw-r--r-- | target/hexagon/cpu.c | 6 | ||||
-rw-r--r-- | target/hexagon/genptr.c | 56 | ||||
-rw-r--r-- | target/hexagon/hex_regs.h | 2 | ||||
-rw-r--r-- | target/hexagon/idef-parser/README.rst | 4 | ||||
-rw-r--r-- | target/hexagon/idef-parser/idef-parser.y | 2 | ||||
-rw-r--r-- | target/hexagon/meson.build | 1 | ||||
-rw-r--r-- | tests/tcg/hexagon/Makefile.target | 2 | ||||
-rw-r--r-- | tests/tcg/hexagon/mem_noshuf.c | 2 | ||||
-rw-r--r-- | tests/tcg/hexagon/misc.c | 6 | ||||
-rw-r--r-- | tests/tcg/hexagon/reg_mut.c | 152 | ||||
-rw-r--r-- | tests/tcg/hexagon/signal_context.c | 84 |
13 files changed, 321 insertions, 31 deletions
diff --git a/linux-user/hexagon/signal.c b/linux-user/hexagon/signal.c index ad4e3822d5..60fa7e1bce 100644 --- a/linux-user/hexagon/signal.c +++ b/linux-user/hexagon/signal.c @@ -39,15 +39,12 @@ struct target_sigcontext { target_ulong m0; target_ulong m1; target_ulong usr; - target_ulong p3_0; target_ulong gp; target_ulong ugp; target_ulong pc; target_ulong cause; target_ulong badva; - target_ulong pad1; - target_ulong pad2; - target_ulong pad3; + target_ulong pred[NUM_PREGS]; }; struct target_ucontext { @@ -118,10 +115,14 @@ static void setup_sigcontext(struct target_sigcontext *sc, CPUHexagonState *env) __put_user(env->gpr[HEX_REG_M0], &sc->m0); __put_user(env->gpr[HEX_REG_M1], &sc->m1); __put_user(env->gpr[HEX_REG_USR], &sc->usr); - __put_user(env->gpr[HEX_REG_P3_0], &sc->p3_0); __put_user(env->gpr[HEX_REG_GP], &sc->gp); __put_user(env->gpr[HEX_REG_UGP], &sc->ugp); __put_user(env->gpr[HEX_REG_PC], &sc->pc); + + int i; + for (i = 0; i < NUM_PREGS; i++) { + __put_user(env->pred[i], &(sc->pred[i])); + } } static void setup_ucontext(struct target_ucontext *uc, @@ -230,10 +231,14 @@ static void restore_sigcontext(CPUHexagonState *env, __get_user(env->gpr[HEX_REG_M0], &sc->m0); __get_user(env->gpr[HEX_REG_M1], &sc->m1); __get_user(env->gpr[HEX_REG_USR], &sc->usr); - __get_user(env->gpr[HEX_REG_P3_0], &sc->p3_0); __get_user(env->gpr[HEX_REG_GP], &sc->gp); __get_user(env->gpr[HEX_REG_UGP], &sc->ugp); __get_user(env->gpr[HEX_REG_PC], &sc->pc); + + int i; + for (i = 0; i < NUM_PREGS; i++) { + __get_user(env->pred[i], &(sc->pred[i])); + } } static void restore_ucontext(CPUHexagonState *env, struct target_ucontext *uc) diff --git a/scripts/meson-buildoptions.sh b/scripts/meson-buildoptions.sh index aa6e30ea91..0f71e92dcb 100644 --- a/scripts/meson-buildoptions.sh +++ b/scripts/meson-buildoptions.sh @@ -10,6 +10,9 @@ meson_options_help() { printf "%s\n" ' affects only QEMU, not tools like qemu-img)' printf "%s\n" ' --datadir=VALUE Data file directory [share]' printf "%s\n" ' --disable-coroutine-pool coroutine freelist (better performance)' + printf "%s\n" ' --disable-hexagon-idef-parser' + printf "%s\n" ' use idef-parser to automatically generate TCG' + printf "%s\n" ' code for the Hexagon frontend' printf "%s\n" ' --disable-install-blobs install provided firmware blobs' printf "%s\n" ' --docdir=VALUE Base directory for documentation installation' printf "%s\n" ' (can be empty) [share/doc]' @@ -40,7 +43,8 @@ meson_options_help() { printf "%s\n" ' --enable-trace-backends=CHOICES' printf "%s\n" ' Set available tracing backends [log] (choices:' printf "%s\n" ' dtrace/ftrace/log/nop/simple/syslog/ust)' - printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-firmware]' + printf "%s\n" ' --firmwarepath=VALUES search PATH for firmware files [share/qemu-' + printf "%s\n" ' firmware]' printf "%s\n" ' --iasl=VALUE Path to ACPI disassembler' printf "%s\n" ' --includedir=VALUE Header file directory [include]' printf "%s\n" ' --interp-prefix=VALUE where to find shared libraries etc., use %M for' @@ -93,7 +97,7 @@ meson_options_help() { printf "%s\n" ' glusterfs Glusterfs block device driver' printf "%s\n" ' gnutls GNUTLS cryptography support' printf "%s\n" ' gtk GTK+ user interface' - printf "%s\n" ' gtk-clipboard clipboard support for GTK (EXPERIMENTAL, MAY HANG)' + printf "%s\n" ' gtk-clipboard clipboard support for the gtk UI (EXPERIMENTAL, MAY HANG)' printf "%s\n" ' guest-agent Build QEMU Guest Agent' printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent' printf "%s\n" ' hax HAX acceleration support' @@ -156,6 +160,8 @@ meson_options_help() { printf "%s\n" ' usb-redir libusbredir support' printf "%s\n" ' vde vde network backend support' printf "%s\n" ' vdi vdi image format support' + printf "%s\n" ' vduse-blk-export' + printf "%s\n" ' VDUSE block export support' printf "%s\n" ' vfio-user-server' printf "%s\n" ' vfio-user server support' printf "%s\n" ' vhost-crypto vhost-user crypto backend support' @@ -164,8 +170,6 @@ meson_options_help() { printf "%s\n" ' vhost-user vhost-user backend support' printf "%s\n" ' vhost-user-blk-server' printf "%s\n" ' build vhost-user-blk server' - printf "%s\n" ' vduse-blk-export' - printf "%s\n" ' VDUSE block export support' printf "%s\n" ' vhost-vdpa vhost-vdpa kernel backend support' printf "%s\n" ' virglrenderer virgl rendering support' printf "%s\n" ' virtfs virtio-9p support' @@ -283,6 +287,8 @@ _meson_option_parse() { --disable-guest-agent-msi) printf "%s" -Dguest_agent_msi=disabled ;; --enable-hax) printf "%s" -Dhax=enabled ;; --disable-hax) printf "%s" -Dhax=disabled ;; + --enable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=true ;; + --disable-hexagon-idef-parser) printf "%s" -Dhexagon_idef_parser=false ;; --enable-hvf) printf "%s" -Dhvf=enabled ;; --disable-hvf) printf "%s" -Dhvf=disabled ;; --iasl=*) quote_sh "-Diasl=$2" ;; @@ -429,6 +435,8 @@ _meson_option_parse() { --disable-vde) printf "%s" -Dvde=disabled ;; --enable-vdi) printf "%s" -Dvdi=enabled ;; --disable-vdi) printf "%s" -Dvdi=disabled ;; + --enable-vduse-blk-export) printf "%s" -Dvduse_blk_export=enabled ;; + --disable-vduse-blk-export) printf "%s" -Dvduse_blk_export=disabled ;; --enable-vfio-user-server) printf "%s" -Dvfio_user_server=enabled ;; --disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;; --enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;; @@ -441,8 +449,6 @@ _meson_option_parse() { --disable-vhost-user) printf "%s" -Dvhost_user=disabled ;; --enable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=enabled ;; --disable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=disabled ;; - --enable-vduse-blk-export) printf "%s" -Dvduse_blk_export=enabled ;; - --disable-vduse-blk-export) printf "%s" -Dvduse_blk_export=disabled ;; --enable-vhost-vdpa) printf "%s" -Dvhost_vdpa=enabled ;; --disable-vhost-vdpa) printf "%s" -Dvhost_vdpa=disabled ;; --enable-virglrenderer) printf "%s" -Dvirglrenderer=enabled ;; diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 658ca4ff78..807037c586 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -86,7 +86,7 @@ static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr) return addr; } -/* HEX_REG_P3_0 (aka C4) is an alias for the predicate registers */ +/* HEX_REG_P3_0_ALIASED (aka C4) is an alias for the predicate registers */ static target_ulong read_p3_0(CPUHexagonState *env) { int32_t control_reg = 0; @@ -102,7 +102,7 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum) { target_ulong value; - if (regnum == HEX_REG_P3_0) { + if (regnum == HEX_REG_P3_0_ALIASED) { value = read_p3_0(env); } else { value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum]) @@ -198,7 +198,7 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags) print_reg(f, env, HEX_REG_M0); print_reg(f, env, HEX_REG_M1); print_reg(f, env, HEX_REG_USR); - print_reg(f, env, HEX_REG_P3_0); + print_reg(f, env, HEX_REG_P3_0_ALIASED); print_reg(f, env, HEX_REG_GP); print_reg(f, env, HEX_REG_UGP); print_reg(f, env, HEX_REG_PC); diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index 6cf2e0ed43..90db99024f 100644 --- a/target/hexagon/genptr.c +++ b/target/hexagon/genptr.c @@ -43,6 +43,33 @@ TCGv gen_read_preg(TCGv pred, uint8_t num) return pred; } +#define IMMUTABLE (~0) + +static const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = { + [HEX_REG_USR] = 0xc13000c0, + [HEX_REG_PC] = IMMUTABLE, + [HEX_REG_GP] = 0x3f, + [HEX_REG_UPCYCLELO] = IMMUTABLE, + [HEX_REG_UPCYCLEHI] = IMMUTABLE, + [HEX_REG_UTIMERLO] = IMMUTABLE, + [HEX_REG_UTIMERHI] = IMMUTABLE, +}; + +static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val, + target_ulong reg_mask) +{ + if (reg_mask) { + TCGv tmp = tcg_temp_new(); + + /* new_val = (new_val & ~reg_mask) | (cur_val & reg_mask) */ + tcg_gen_andi_tl(new_val, new_val, ~reg_mask); + tcg_gen_andi_tl(tmp, cur_val, reg_mask); + tcg_gen_or_tl(new_val, new_val, tmp); + + tcg_temp_free(tmp); + } +} + static inline void gen_log_predicated_reg_write(int rnum, TCGv val, uint32_t slot) { @@ -69,6 +96,9 @@ static inline void gen_log_predicated_reg_write(int rnum, TCGv val, void gen_log_reg_write(int rnum, TCGv val) { + const target_ulong reg_mask = reg_immut_masks[rnum]; + + gen_masked_reg_write(val, hex_gpr[rnum], reg_mask); tcg_gen_mov_tl(hex_new_value[rnum], val); if (HEX_DEBUG) { /* Do this so HELPER(debug_commit_end) will know */ @@ -114,19 +144,29 @@ static void gen_log_predicated_reg_write_pair(int rnum, TCGv_i64 val, static void gen_log_reg_write_pair(int rnum, TCGv_i64 val) { + const target_ulong reg_mask_low = reg_immut_masks[rnum]; + const target_ulong reg_mask_high = reg_immut_masks[rnum + 1]; + TCGv val32 = tcg_temp_new(); + /* Low word */ - tcg_gen_extrl_i64_i32(hex_new_value[rnum], val); + tcg_gen_extrl_i64_i32(val32, val); + gen_masked_reg_write(val32, hex_gpr[rnum], reg_mask_low); + tcg_gen_mov_tl(hex_new_value[rnum], val32); if (HEX_DEBUG) { /* Do this so HELPER(debug_commit_end) will know */ tcg_gen_movi_tl(hex_reg_written[rnum], 1); } /* High word */ - tcg_gen_extrh_i64_i32(hex_new_value[rnum + 1], val); + tcg_gen_extrh_i64_i32(val32, val); + gen_masked_reg_write(val32, hex_gpr[rnum + 1], reg_mask_high); + tcg_gen_mov_tl(hex_new_value[rnum + 1], val32); if (HEX_DEBUG) { /* Do this so HELPER(debug_commit_end) will know */ tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1); } + + tcg_temp_free(val32); } void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val) @@ -163,7 +203,7 @@ static inline void gen_read_p3_0(TCGv control_reg) /* * Certain control registers require special handling on read - * HEX_REG_P3_0 aliased to the predicate registers + * HEX_REG_P3_0_ALIASED aliased to the predicate registers * -> concat the 4 predicate registers together * HEX_REG_PC actual value stored in DisasContext * -> assign from ctx->base.pc_next @@ -173,7 +213,7 @@ static inline void gen_read_p3_0(TCGv control_reg) static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num, TCGv dest) { - if (reg_num == HEX_REG_P3_0) { + if (reg_num == HEX_REG_P3_0_ALIASED) { gen_read_p3_0(dest); } else if (reg_num == HEX_REG_PC) { tcg_gen_movi_tl(dest, ctx->base.pc_next); @@ -194,7 +234,7 @@ static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num, static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num, TCGv_i64 dest) { - if (reg_num == HEX_REG_P3_0) { + if (reg_num == HEX_REG_P3_0_ALIASED) { TCGv p3_0 = tcg_temp_new(); gen_read_p3_0(p3_0); tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]); @@ -238,7 +278,7 @@ static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg) /* * Certain control registers require special handling on write - * HEX_REG_P3_0 aliased to the predicate registers + * HEX_REG_P3_0_ALIASED aliased to the predicate registers * -> break the value across 4 predicate registers * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext * -> clear the changes @@ -246,7 +286,7 @@ static void gen_write_p3_0(DisasContext *ctx, TCGv control_reg) static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num, TCGv val) { - if (reg_num == HEX_REG_P3_0) { + if (reg_num == HEX_REG_P3_0_ALIASED) { gen_write_p3_0(ctx, val); } else { gen_log_reg_write(reg_num, val); @@ -266,7 +306,7 @@ static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num, static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num, TCGv_i64 val) { - if (reg_num == HEX_REG_P3_0) { + if (reg_num == HEX_REG_P3_0_ALIASED) { TCGv val32 = tcg_temp_new(); tcg_gen_extrl_i64_i32(val32, val); gen_write_p3_0(ctx, val32); diff --git a/target/hexagon/hex_regs.h b/target/hexagon/hex_regs.h index a63c2c0fd5..bddfc28021 100644 --- a/target/hexagon/hex_regs.h +++ b/target/hexagon/hex_regs.h @@ -58,7 +58,7 @@ enum { HEX_REG_LC0 = 33, HEX_REG_SA1 = 34, HEX_REG_LC1 = 35, - HEX_REG_P3_0 = 36, + HEX_REG_P3_0_ALIASED = 36, HEX_REG_M0 = 38, HEX_REG_M1 = 39, HEX_REG_USR = 40, diff --git a/target/hexagon/idef-parser/README.rst b/target/hexagon/idef-parser/README.rst index 65e6bf4ee5..ff6d14150a 100644 --- a/target/hexagon/idef-parser/README.rst +++ b/target/hexagon/idef-parser/README.rst @@ -552,11 +552,11 @@ to compare our buggy CPU state against, running :: - meson configure -Dhexagon_idef_parser_enabled=false + meson configure -Dhexagon_idef_parser=false will disable the idef-parser for all instructions and fallback on manual tinycode generator overrides, or on helper function implementations. Recompiling -gives us ``qemu-hexagon`` which passes all tests. If ``qemu-heaxgon-buggy`` is +gives us ``qemu-hexagon`` which passes all tests. If ``qemu-hexagon-buggy`` is our binary with the incorrect tinycode generators, we can compare the CPU state between the two versions diff --git a/target/hexagon/idef-parser/idef-parser.y b/target/hexagon/idef-parser/idef-parser.y index 8be44a0ad1..c14cb39500 100644 --- a/target/hexagon/idef-parser/idef-parser.y +++ b/target/hexagon/idef-parser/idef-parser.y @@ -99,6 +99,8 @@ /* Input file containing the description of each hexagon instruction */ input : instructions { + /* Suppress warning about unused yynerrs */ + (void) yynerrs; YYACCEPT; } ; diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build index e8f250fcac..c9d31d095c 100644 --- a/target/hexagon/meson.build +++ b/target/hexagon/meson.build @@ -197,7 +197,6 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs idef_parser_dir / 'parser-helpers.c'], include_directories: ['idef-parser', '../../include/'], dependencies: [glib_dep], - c_args: ['-Wextra'], native: true ) diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 9ee1faa1e1..18e6a5969e 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -43,6 +43,8 @@ HEX_TESTS += load_align HEX_TESTS += atomics HEX_TESTS += fpstuff HEX_TESTS += overflow +HEX_TESTS += signal_context +HEX_TESTS += reg_mut HEX_TESTS += test_abs HEX_TESTS += test_bitcnt diff --git a/tests/tcg/hexagon/mem_noshuf.c b/tests/tcg/hexagon/mem_noshuf.c index 0f4064e700..210b2f1208 100644 --- a/tests/tcg/hexagon/mem_noshuf.c +++ b/tests/tcg/hexagon/mem_noshuf.c @@ -144,7 +144,7 @@ static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q, "}:mem_noshuf\n" : "=&r"(ret) : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) - : "p0", "memory"); + : "r7", "p0", "memory"); return ret; } diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c index f0b1947fb3..e73ab57334 100644 --- a/tests/tcg/hexagon/misc.c +++ b/tests/tcg/hexagon/misc.c @@ -186,10 +186,10 @@ static int L2_ploadrifnew_pi(void *p, int pred) int result; asm volatile("%0 = #31\n\t" "{\n\t" - " p0 = cmp.eq(%1, #1)\n\t" - " if (!p0.new) %0 = memw(%2++#4)\n\t" + " p0 = cmp.eq(%2, #1)\n\t" + " if (!p0.new) %0 = memw(%1++#4)\n\t" "}\n\t" - : "=r"(result) : "r"(pred), "r"(p) + : "=&r"(result), "+r"(p) : "r"(pred) : "p0"); return result; } diff --git a/tests/tcg/hexagon/reg_mut.c b/tests/tcg/hexagon/reg_mut.c new file mode 100644 index 0000000000..910e663ace --- /dev/null +++ b/tests/tcg/hexagon/reg_mut.c @@ -0,0 +1,152 @@ + +/* + * Copyright(c) 2022 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdint.h> + +static int err; + +#define check(N, EXPECT) \ + do { \ + uint64_t value = N; \ + uint64_t expect = EXPECT; \ + if (value != EXPECT) { \ + printf("ERROR: \"%s\" 0x%04llx != 0x%04llx at %s:%d\n", #N, value, \ + expect, __FILE__, __LINE__); \ + err++; \ + } \ + } while (0) + +#define check_ne(N, EXPECT) \ + do { \ + uint64_t value = N; \ + uint64_t expect = EXPECT; \ + if (value == EXPECT) { \ + printf("ERROR: \"%s\" 0x%04llx == 0x%04llx at %s:%d\n", #N, value, \ + expect, __FILE__, __LINE__); \ + err++; \ + } \ + } while (0) + +#define WRITE_REG_NOCLOBBER(output, reg_name, input) \ + asm volatile(reg_name " = %1\n\t" \ + "%0 = " reg_name "\n\t" \ + : "=r"(output) \ + : "r"(input) \ + : ); + +#define WRITE_REG_ENCODED(output, reg_name, input, encoding) \ + asm volatile("r0 = %1\n\t" \ + encoding "\n\t" \ + "%0 = " reg_name "\n\t" \ + : "=r"(output) \ + : "r"(input) \ + : "r0"); + +#define WRITE_REG_PAIR_ENCODED(output, reg_name, input, encoding) \ + asm volatile("r1:0 = %1\n\t" \ + encoding "\n\t" \ + "%0 = " reg_name "\n\t" \ + : "=r"(output) \ + : "r"(input) \ + : "r1:0"); + +/* + * Instruction word: { pc = r0 } + * + * This instruction is barred by the assembler. + * + * 3 2 1 + * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Opc[A2_tfrrcr] | Src[R0] |P P| | C9/PC | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + */ +#define PC_EQ_R0 ".word 0x6220c009" +#define C9_8_EQ_R1_0 ".word 0x6320c008" + +static inline void write_control_registers(void) +{ + uint32_t result = 0; + + WRITE_REG_NOCLOBBER(result, "usr", 0xffffffff); + check(result, 0x3ecfff3f); + + WRITE_REG_NOCLOBBER(result, "gp", 0xffffffff); + check(result, 0xffffffc0); + + WRITE_REG_NOCLOBBER(result, "upcyclelo", 0xffffffff); + check(result, 0x00000000); + + WRITE_REG_NOCLOBBER(result, "upcyclehi", 0xffffffff); + check(result, 0x00000000); + + WRITE_REG_NOCLOBBER(result, "utimerlo", 0xffffffff); + check(result, 0x00000000); + + WRITE_REG_NOCLOBBER(result, "utimerhi", 0xffffffff); + check(result, 0x00000000); + + /* + * PC is special. Setting it to these values + * should cause a catastrophic failure. + */ + WRITE_REG_ENCODED(result, "pc", 0x00000000, PC_EQ_R0); + check_ne(result, 0x00000000); + + WRITE_REG_ENCODED(result, "pc", 0x00000001, PC_EQ_R0); + check_ne(result, 0x00000001); + + WRITE_REG_ENCODED(result, "pc", 0xffffffff, PC_EQ_R0); + check_ne(result, 0xffffffff); +} + +static inline void write_control_register_pairs(void) +{ + uint64_t result = 0; + + WRITE_REG_NOCLOBBER(result, "c11:10", 0xffffffffffffffff); + check(result, 0xffffffc0ffffffff); + + WRITE_REG_NOCLOBBER(result, "c15:14", 0xffffffffffffffff); + check(result, 0x0000000000000000); + + WRITE_REG_NOCLOBBER(result, "c31:30", 0xffffffffffffffff); + check(result, 0x0000000000000000); + + WRITE_REG_PAIR_ENCODED(result, "c9:8", (uint64_t) 0x0000000000000000, + C9_8_EQ_R1_0); + check_ne(result, 0x000000000000000); + + WRITE_REG_PAIR_ENCODED(result, "c9:8", 0x0000000100000000, C9_8_EQ_R1_0); + check_ne(result, 0x0000000100000000); + + WRITE_REG_PAIR_ENCODED(result, "c9:8", 0xffffffffffffffff, C9_8_EQ_R1_0); + check_ne(result, 0xffffffffffffffff); +} + +int main() +{ + err = 0; + + write_control_registers(); + write_control_register_pairs(); + + puts(err ? "FAIL" : "PASS"); + return err; +} diff --git a/tests/tcg/hexagon/signal_context.c b/tests/tcg/hexagon/signal_context.c new file mode 100644 index 0000000000..7202fa64b6 --- /dev/null +++ b/tests/tcg/hexagon/signal_context.c @@ -0,0 +1,84 @@ +/* + * Copyright(c) 2022 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <signal.h> +#include <time.h> + +void sig_user(int sig, siginfo_t *info, void *puc) +{ + asm("r7 = #0\n\t" + "p0 = r7\n\t" + "p1 = r7\n\t" + "p2 = r7\n\t" + "p3 = r7\n\t" + : : : "r7", "p0", "p1", "p2", "p3"); +} + +int main() +{ + int err = 0; + unsigned int i = 100000; + struct sigaction act; + struct itimerspec it; + timer_t tid; + struct sigevent sev; + + act.sa_sigaction = sig_user; + sigemptyset(&act.sa_mask); + act.sa_flags = SA_SIGINFO; + sigaction(SIGUSR1, &act, NULL); + sev.sigev_notify = SIGEV_SIGNAL; + sev.sigev_signo = SIGUSR1; + sev.sigev_value.sival_ptr = &tid; + timer_create(CLOCK_REALTIME, &sev, &tid); + it.it_interval.tv_sec = 0; + it.it_interval.tv_nsec = 100000; + it.it_value.tv_sec = 0; + it.it_value.tv_nsec = 100000; + timer_settime(tid, 0, &it, NULL); + + asm("loop0(1f, %1)\n\t" + "1: r8 = #0xff\n\t" + " p0 = r8\n\t" + " p1 = r8\n\t" + " p2 = r8\n\t" + " p3 = r8\n\t" + " jump 3f\n\t" + "2: memb(%0) = #1\n\t" + " jump 4f\n\t" + "3:\n\t" + " r8 = p0\n\t" + " p0 = cmp.eq(r8, #0xff)\n\t" + " if (!p0) jump 2b\n\t" + " r8 = p1\n\t" + " p0 = cmp.eq(r8, #0xff)\n\t" + " if (!p0) jump 2b\n\t" + " r8 = p2\n\t" + " p0 = cmp.eq(r8, #0xff)\n\t" + " if (!p0) jump 2b\n\t" + " r8 = p3\n\t" + " p0 = cmp.eq(r8, #0xff)\n\t" + " if (!p0) jump 2b\n\t" + "4: {}: endloop0\n\t" + : + : "r"(&err), "r"(i) + : "memory", "r8", "p0", "p1", "p2", "p3"); + + puts(err ? "FAIL" : "PASS"); + return err; +} |