Hexagon update: patches from several folks

-----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEENjXHiM5iuR/UxZq0ewJE+xLeRCIFAmO3Cl8ACgkQewJE+xLe
 RCKopQf/eVpmA04C792MIYHJnAaASbXZ1FA2Q33l9zrPt9V5oL0cer+rNPlqwVIb
 jUdFLrT6ppe3jgkzeZVzLTGoNiLO1BnpH3+NV5ZpnMBON4g6/uyagRJekvb5xcDw
 a832LM77zWrSQbV+Z3C0sn87j7u0YFYiXtya3mJUv6iSfKZnR4bGZH+LW2dOrnXn
 +uMGnjjUQ2Ac7mvHTnrtooVUNhgRpTq4tMBwl1mE/hacUuejBjDgMLHDb6e4yPC7
 g0/BuMB1ygBYFDINJ9El5oD0JtYHZjHOX4TKs6i0oXntoeveut62oGRwgLrk8eRe
 lwKiEvFNrz/RYmCIy8Pz7s+5HQUgqA==
 =/i3r
 -----END PGP SIGNATURE-----

Merge tag 'pull-hex-20230105' of https://github.com/quic/qemu into staging

Hexagon update: patches from several folks

# gpg: Signature made Thu 05 Jan 2023 17:35:27 GMT
# gpg:                using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422
# gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 3635 C788 CE62 B91F D4C5  9AB4 7B02 44FB 12DE 4422

* tag 'pull-hex-20230105' of https://github.com/quic/qemu:
  Update scripts/meson-buildoptions.sh
  Hexagon (target/hexagon) implement mutability mask for GPRs
  target/hexagon: suppress unused variable warning
  target/hexagon/idef-parser: fix two typos in README
  tests/tcg/hexagon: fix underspecifed asm constraints
  target/hexagon: rename aliased register HEX_REG_P3_0
  linux-user/hexagon: fix signal context save & restore

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2023-01-06 12:11:22 +00:00
commit 171033e8db
13 changed files with 321 additions and 31 deletions

View file

@ -39,15 +39,12 @@ struct target_sigcontext {
target_ulong m0; target_ulong m0;
target_ulong m1; target_ulong m1;
target_ulong usr; target_ulong usr;
target_ulong p3_0;
target_ulong gp; target_ulong gp;
target_ulong ugp; target_ulong ugp;
target_ulong pc; target_ulong pc;
target_ulong cause; target_ulong cause;
target_ulong badva; target_ulong badva;
target_ulong pad1; target_ulong pred[NUM_PREGS];
target_ulong pad2;
target_ulong pad3;
}; };
struct target_ucontext { 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_M0], &sc->m0);
__put_user(env->gpr[HEX_REG_M1], &sc->m1); __put_user(env->gpr[HEX_REG_M1], &sc->m1);
__put_user(env->gpr[HEX_REG_USR], &sc->usr); __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_GP], &sc->gp);
__put_user(env->gpr[HEX_REG_UGP], &sc->ugp); __put_user(env->gpr[HEX_REG_UGP], &sc->ugp);
__put_user(env->gpr[HEX_REG_PC], &sc->pc); __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, 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_M0], &sc->m0);
__get_user(env->gpr[HEX_REG_M1], &sc->m1); __get_user(env->gpr[HEX_REG_M1], &sc->m1);
__get_user(env->gpr[HEX_REG_USR], &sc->usr); __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_GP], &sc->gp);
__get_user(env->gpr[HEX_REG_UGP], &sc->ugp); __get_user(env->gpr[HEX_REG_UGP], &sc->ugp);
__get_user(env->gpr[HEX_REG_PC], &sc->pc); __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) static void restore_ucontext(CPUHexagonState *env, struct target_ucontext *uc)

View file

@ -10,6 +10,9 @@ meson_options_help() {
printf "%s\n" ' affects only QEMU, not tools like qemu-img)' printf "%s\n" ' affects only QEMU, not tools like qemu-img)'
printf "%s\n" ' --datadir=VALUE Data file directory [share]' printf "%s\n" ' --datadir=VALUE Data file directory [share]'
printf "%s\n" ' --disable-coroutine-pool coroutine freelist (better performance)' 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" ' --disable-install-blobs install provided firmware blobs'
printf "%s\n" ' --docdir=VALUE Base directory for documentation installation' printf "%s\n" ' --docdir=VALUE Base directory for documentation installation'
printf "%s\n" ' (can be empty) [share/doc]' 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" ' --enable-trace-backends=CHOICES'
printf "%s\n" ' Set available tracing backends [log] (choices:' printf "%s\n" ' Set available tracing backends [log] (choices:'
printf "%s\n" ' dtrace/ftrace/log/nop/simple/syslog/ust)' 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" ' --iasl=VALUE Path to ACPI disassembler'
printf "%s\n" ' --includedir=VALUE Header file directory [include]' printf "%s\n" ' --includedir=VALUE Header file directory [include]'
printf "%s\n" ' --interp-prefix=VALUE where to find shared libraries etc., use %M for' 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" ' glusterfs Glusterfs block device driver'
printf "%s\n" ' gnutls GNUTLS cryptography support' printf "%s\n" ' gnutls GNUTLS cryptography support'
printf "%s\n" ' gtk GTK+ user interface' 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 Build QEMU Guest Agent'
printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent' printf "%s\n" ' guest-agent-msi Build MSI package for the QEMU Guest Agent'
printf "%s\n" ' hax HAX acceleration support' printf "%s\n" ' hax HAX acceleration support'
@ -156,6 +160,8 @@ meson_options_help() {
printf "%s\n" ' usb-redir libusbredir support' printf "%s\n" ' usb-redir libusbredir support'
printf "%s\n" ' vde vde network backend support' printf "%s\n" ' vde vde network backend support'
printf "%s\n" ' vdi vdi image format 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'
printf "%s\n" ' vfio-user server support' printf "%s\n" ' vfio-user server support'
printf "%s\n" ' vhost-crypto vhost-user crypto backend 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 vhost-user backend support'
printf "%s\n" ' vhost-user-blk-server' printf "%s\n" ' vhost-user-blk-server'
printf "%s\n" ' build 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" ' vhost-vdpa vhost-vdpa kernel backend support'
printf "%s\n" ' virglrenderer virgl rendering support' printf "%s\n" ' virglrenderer virgl rendering support'
printf "%s\n" ' virtfs virtio-9p 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 ;; --disable-guest-agent-msi) printf "%s" -Dguest_agent_msi=disabled ;;
--enable-hax) printf "%s" -Dhax=enabled ;; --enable-hax) printf "%s" -Dhax=enabled ;;
--disable-hax) printf "%s" -Dhax=disabled ;; --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 ;; --enable-hvf) printf "%s" -Dhvf=enabled ;;
--disable-hvf) printf "%s" -Dhvf=disabled ;; --disable-hvf) printf "%s" -Dhvf=disabled ;;
--iasl=*) quote_sh "-Diasl=$2" ;; --iasl=*) quote_sh "-Diasl=$2" ;;
@ -429,6 +435,8 @@ _meson_option_parse() {
--disable-vde) printf "%s" -Dvde=disabled ;; --disable-vde) printf "%s" -Dvde=disabled ;;
--enable-vdi) printf "%s" -Dvdi=enabled ;; --enable-vdi) printf "%s" -Dvdi=enabled ;;
--disable-vdi) printf "%s" -Dvdi=disabled ;; --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 ;; --enable-vfio-user-server) printf "%s" -Dvfio_user_server=enabled ;;
--disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;; --disable-vfio-user-server) printf "%s" -Dvfio_user_server=disabled ;;
--enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;; --enable-vhost-crypto) printf "%s" -Dvhost_crypto=enabled ;;
@ -441,8 +449,6 @@ _meson_option_parse() {
--disable-vhost-user) printf "%s" -Dvhost_user=disabled ;; --disable-vhost-user) printf "%s" -Dvhost_user=disabled ;;
--enable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=enabled ;; --enable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=enabled ;;
--disable-vhost-user-blk-server) printf "%s" -Dvhost_user_blk_server=disabled ;; --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 ;; --enable-vhost-vdpa) printf "%s" -Dvhost_vdpa=enabled ;;
--disable-vhost-vdpa) printf "%s" -Dvhost_vdpa=disabled ;; --disable-vhost-vdpa) printf "%s" -Dvhost_vdpa=disabled ;;
--enable-virglrenderer) printf "%s" -Dvirglrenderer=enabled ;; --enable-virglrenderer) printf "%s" -Dvirglrenderer=enabled ;;

View file

@ -86,7 +86,7 @@ static target_ulong adjust_stack_ptrs(CPUHexagonState *env, target_ulong addr)
return 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) static target_ulong read_p3_0(CPUHexagonState *env)
{ {
int32_t control_reg = 0; int32_t control_reg = 0;
@ -102,7 +102,7 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
{ {
target_ulong value; target_ulong value;
if (regnum == HEX_REG_P3_0) { if (regnum == HEX_REG_P3_0_ALIASED) {
value = read_p3_0(env); value = read_p3_0(env);
} else { } else {
value = regnum < 32 ? adjust_stack_ptrs(env, env->gpr[regnum]) 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_M0);
print_reg(f, env, HEX_REG_M1); print_reg(f, env, HEX_REG_M1);
print_reg(f, env, HEX_REG_USR); 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_GP);
print_reg(f, env, HEX_REG_UGP); print_reg(f, env, HEX_REG_UGP);
print_reg(f, env, HEX_REG_PC); print_reg(f, env, HEX_REG_PC);

View file

@ -43,6 +43,33 @@ TCGv gen_read_preg(TCGv pred, uint8_t num)
return pred; 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, static inline void gen_log_predicated_reg_write(int rnum, TCGv val,
uint32_t slot) 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) 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); tcg_gen_mov_tl(hex_new_value[rnum], val);
if (HEX_DEBUG) { if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */ /* 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) 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 */ /* 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) { if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */ /* Do this so HELPER(debug_commit_end) will know */
tcg_gen_movi_tl(hex_reg_written[rnum], 1); tcg_gen_movi_tl(hex_reg_written[rnum], 1);
} }
/* High word */ /* 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) { if (HEX_DEBUG) {
/* Do this so HELPER(debug_commit_end) will know */ /* Do this so HELPER(debug_commit_end) will know */
tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1); 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) 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 * 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 * -> concat the 4 predicate registers together
* HEX_REG_PC actual value stored in DisasContext * HEX_REG_PC actual value stored in DisasContext
* -> assign from ctx->base.pc_next * -> 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, static inline void gen_read_ctrl_reg(DisasContext *ctx, const int reg_num,
TCGv dest) TCGv dest)
{ {
if (reg_num == HEX_REG_P3_0) { if (reg_num == HEX_REG_P3_0_ALIASED) {
gen_read_p3_0(dest); gen_read_p3_0(dest);
} else if (reg_num == HEX_REG_PC) { } else if (reg_num == HEX_REG_PC) {
tcg_gen_movi_tl(dest, ctx->base.pc_next); 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, static inline void gen_read_ctrl_reg_pair(DisasContext *ctx, const int reg_num,
TCGv_i64 dest) TCGv_i64 dest)
{ {
if (reg_num == HEX_REG_P3_0) { if (reg_num == HEX_REG_P3_0_ALIASED) {
TCGv p3_0 = tcg_temp_new(); TCGv p3_0 = tcg_temp_new();
gen_read_p3_0(p3_0); gen_read_p3_0(p3_0);
tcg_gen_concat_i32_i64(dest, p3_0, hex_gpr[reg_num + 1]); 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 * 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 * -> break the value across 4 predicate registers
* HEX_REG_QEMU_*_CNT changes in current TB in DisasContext * HEX_REG_QEMU_*_CNT changes in current TB in DisasContext
* -> clear the changes * -> 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, static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
TCGv val) TCGv val)
{ {
if (reg_num == HEX_REG_P3_0) { if (reg_num == HEX_REG_P3_0_ALIASED) {
gen_write_p3_0(ctx, val); gen_write_p3_0(ctx, val);
} else { } else {
gen_log_reg_write(reg_num, val); 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, static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
TCGv_i64 val) TCGv_i64 val)
{ {
if (reg_num == HEX_REG_P3_0) { if (reg_num == HEX_REG_P3_0_ALIASED) {
TCGv val32 = tcg_temp_new(); TCGv val32 = tcg_temp_new();
tcg_gen_extrl_i64_i32(val32, val); tcg_gen_extrl_i64_i32(val32, val);
gen_write_p3_0(ctx, val32); gen_write_p3_0(ctx, val32);

View file

@ -58,7 +58,7 @@ enum {
HEX_REG_LC0 = 33, HEX_REG_LC0 = 33,
HEX_REG_SA1 = 34, HEX_REG_SA1 = 34,
HEX_REG_LC1 = 35, HEX_REG_LC1 = 35,
HEX_REG_P3_0 = 36, HEX_REG_P3_0_ALIASED = 36,
HEX_REG_M0 = 38, HEX_REG_M0 = 38,
HEX_REG_M1 = 39, HEX_REG_M1 = 39,
HEX_REG_USR = 40, HEX_REG_USR = 40,

View file

@ -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 will disable the idef-parser for all instructions and fallback on manual
tinycode generator overrides, or on helper function implementations. Recompiling 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 our binary with the incorrect tinycode generators, we can compare the CPU state
between the two versions between the two versions

View file

@ -99,6 +99,8 @@
/* Input file containing the description of each hexagon instruction */ /* Input file containing the description of each hexagon instruction */
input : instructions input : instructions
{ {
/* Suppress warning about unused yynerrs */
(void) yynerrs;
YYACCEPT; YYACCEPT;
} }
; ;

View file

@ -197,7 +197,6 @@ if idef_parser_enabled and 'hexagon-linux-user' in target_dirs
idef_parser_dir / 'parser-helpers.c'], idef_parser_dir / 'parser-helpers.c'],
include_directories: ['idef-parser', '../../include/'], include_directories: ['idef-parser', '../../include/'],
dependencies: [glib_dep], dependencies: [glib_dep],
c_args: ['-Wextra'],
native: true native: true
) )

View file

@ -43,6 +43,8 @@ HEX_TESTS += load_align
HEX_TESTS += atomics HEX_TESTS += atomics
HEX_TESTS += fpstuff HEX_TESTS += fpstuff
HEX_TESTS += overflow HEX_TESTS += overflow
HEX_TESTS += signal_context
HEX_TESTS += reg_mut
HEX_TESTS += test_abs HEX_TESTS += test_abs
HEX_TESTS += test_bitcnt HEX_TESTS += test_bitcnt

View file

@ -144,7 +144,7 @@ static inline long long pred_ld_sd_pi(int pred, long long *p, long long *q,
"}:mem_noshuf\n" "}:mem_noshuf\n"
: "=&r"(ret) : "=&r"(ret)
: "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred) : "r"(p), "r"(q), "r"(x), "r"(y), "r"(pred)
: "p0", "memory"); : "r7", "p0", "memory");
return ret; return ret;
} }

View file

@ -186,10 +186,10 @@ static int L2_ploadrifnew_pi(void *p, int pred)
int result; int result;
asm volatile("%0 = #31\n\t" asm volatile("%0 = #31\n\t"
"{\n\t" "{\n\t"
" p0 = cmp.eq(%1, #1)\n\t" " p0 = cmp.eq(%2, #1)\n\t"
" if (!p0.new) %0 = memw(%2++#4)\n\t" " if (!p0.new) %0 = memw(%1++#4)\n\t"
"}\n\t" "}\n\t"
: "=r"(result) : "r"(pred), "r"(p) : "=&r"(result), "+r"(p) : "r"(pred)
: "p0"); : "p0");
return result; return result;
} }

152
tests/tcg/hexagon/reg_mut.c Normal file
View file

@ -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;
}

View file

@ -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;
}