mirror of https://github.com/xemu-project/xemu.git
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:
commit
171033e8db
|
@ -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)
|
||||
|
|
|
@ -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 ;;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@
|
|||
/* Input file containing the description of each hexagon instruction */
|
||||
input : instructions
|
||||
{
|
||||
/* Suppress warning about unused yynerrs */
|
||||
(void) yynerrs;
|
||||
YYACCEPT;
|
||||
}
|
||||
;
|
||||
|
|
|
@ -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
|
||||
)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue