Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -1890,6 +1890,7 @@
/none/tests/arm64/ldxp_stxp
/none/tests/arm64/integer
/none/tests/arm64/memory_test
/none/tests/arm64/mrs_id_regs
/none/tests/arm64/simd_dotprod
/none/tests/arm64/simd_v81
/none/tests/arm64/sha512_v82
Expand Down
10 changes: 10 additions & 0 deletions CODSPEED-CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ last-level cache when `--LL` (or its `--L2` alias) supplies the cache configurat
The warning remains when LL is auto-detected. Cache geometry and simulation
results are unchanged.

### arm64: decode reads of all EL0-visible ID registers

Previously unsupported `MRS` reads in `S3_0_C0_C2_0` through `S3_0_C0_C7_7`
now return 0 instead of raising SIGILL, reporting the features as absent.
Linux emulates these reads natively. The decoder label for `ID_AA64PFR2_EL1`
was also corrected from `ID_AA64ZFR0_EL1`.

`MRS` reads of `TPIDRRO_EL0` now return 0 instead of raising SIGILL,
matching Linux on AArch64.

## Features

### Fixed Linux startup stack layout
Expand Down
37 changes: 34 additions & 3 deletions VEX/priv/guest_arm64_toIR.c
Original file line number Diff line number Diff line change
Expand Up @@ -7635,15 +7635,15 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
DIP("mrs %s, id_aa64pfr1_el1 (FAKED)\n", nameIReg32orZR(tt));
return True;
}
/* ---- Case for ID_AA64ZFR0_EL1 (RO) ----
/* ---- Case for ID_AA64PFR2_EL1 (RO) ----
We just return 0x0 here, as we don't support the opcodes of
new commands in the emulation environment.
0xD53804 010 Rt MRS rT, id_aa64zfr0_el1
0xD53804 010 Rt MRS rT, id_aa64pfr2_el1
*/
if ((INSN(31,0) & 0xFFFFFFE0) == 0xD5380440 /*MRS*/) {
UInt tt = INSN(4,0);
putIReg64orZR(tt, mkU64(0x0));
DIP("mrs %s, id_aa64zfr0_el1 (FAKED)\n", nameIReg64orZR(tt));
DIP("mrs %s, id_aa64pfr2_el1 (FAKED)\n", nameIReg64orZR(tt));
return True;
}
/* ---- Case for ID_AA64DFR0_EL1 (RO) ----
Expand Down Expand Up @@ -7790,6 +7790,25 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
DIP("mrs %s, id_aa64mmfr2_el1 (FAKED)\n", nameIReg64orZR(tt));
return True;
}
/* ---- Case for the remaining ID registers (RO) ----
Linux emulates EL0 reads of Op0=3, Op1=0, CRn=0, CRm=2..7 and
returns 0 for every register it does not track, so a read never
traps natively. This covers ID_AA64ZFR0_EL1, ID_AA64SMFR0_EL1,
ID_AA64FPFR0_EL1, ID_AA64ISAR2_EL1, ID_AA64MMFR3_EL1, the AArch32
ID registers and unallocated encodings. Return 0 for all of them:
it reports the features as absent, which matches what the cases
above report for ID_AA64PFR0_EL1 (no SVE) and ID_AA64PFR1_EL1
(no SME).
0xD538 0 CRm op2 Rt MRS rT, s3_0_c0_c<CRm>_<op2>
*/
if ((INSN(31,0) & 0xFFFFF000) == 0xD5380000 /*MRS*/
&& INSN(11,8) >= 2 && INSN(11,8) <= 7) {
UInt tt = INSN(4,0);
putIReg64orZR(tt, mkU64(0x0));
DIP("mrs %s, s3_0_c0_c%u_%u (FAKED)\n",
nameIReg64orZR(tt), INSN(11,8), INSN(7,5));
return True;
}
/* ---- Cases for TPIDR_EL0 ----
0xD51BD0 010 Rt MSR tpidr_el0, rT
0xD53BD0 010 Rt MRS rT, tpidr_el0
Expand All @@ -7807,6 +7826,18 @@ Bool dis_ARM64_branch_etc(/*MB_OUT*/DisResult* dres, UInt insn,
}
return True;
}
/* ---- Case for TPIDRRO_EL0 (RO) ----
EL0 can read but not write it. Linux zeroes it for AArch64
tasks (it holds the TLS pointer only for AArch32 tasks), so
return 0.
0xD53BD0 011 Rt MRS rT, tpidrro_el0
*/
if ((INSN(31,0) & 0xFFFFFFE0) == 0xD53BD060 /*MRS*/) {
UInt tt = INSN(4,0);
putIReg64orZR(tt, mkU64(0x0));
DIP("mrs %s, tpidrro_el0 (FAKED)\n", nameIReg64orZR(tt));
return True;
}
/* ---- Cases for FPCR ----
0xD51B44 000 Rt MSR fpcr, rT
0xD53B44 000 Rt MSR rT, fpcr
Expand Down
2 changes: 2 additions & 0 deletions none/tests/arm64/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ EXTRA_DIST = \
integer.stdout.exp integer.stderr.exp integer.vgtest \
memory_test.stdout.exp memory_test.stderr.exp memory_test.vgtest \
memory_test.stdout.exp-clang \
mrs_id_regs.stdout.exp mrs_id_regs.stderr.exp mrs_id_regs.vgtest \
atomics_v81.stdout.exp atomics_v81.stderr.exp atomics_v81.vgtest \
simd_v81.stdout.exp simd_v81.stderr.exp simd_v81.vgtest \
simd_dotprod.stdout.exp simd_dotprod.stderr.exp simd_dotprod.vgtest \
Expand All @@ -39,6 +40,7 @@ check_PROGRAMS = \
fp_and_simd \
integer \
memory_test \
mrs_id_regs \
fmadd_sub \
ldxp_stxp

Expand Down
32 changes: 32 additions & 0 deletions none/tests/arm64/mrs_id_regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Linux lets EL0 read the ID registers in Op0=3, Op1=0, CRn=0, CRm=2..7
(by emulating the read) and TPIDRRO_EL0, so these reads must not raise
SIGILL under Valgrind. Valgrind reports the ID register features as
absent, and Linux zeroes TPIDRRO_EL0 for AArch64 tasks, so each read
returns 0. */

#include <stdio.h>

#define READ_ID_REG(name, sysreg) \
do { \
unsigned long value; \
__asm__ volatile("mrs %0, " sysreg : "=r"(value)); \
printf("%-17s 0x%016lx\n", name, value); \
} while (0)

int main(void)
{
READ_ID_REG("ID_ISAR0_EL1", "S3_0_C0_C2_0");
READ_ID_REG("MVFR0_EL1", "S3_0_C0_C3_0");
READ_ID_REG("ID_AA64PFR2_EL1", "S3_0_C0_C4_2");
READ_ID_REG("ID_AA64ZFR0_EL1", "S3_0_C0_C4_4");
READ_ID_REG("ID_AA64SMFR0_EL1", "S3_0_C0_C4_5");
READ_ID_REG("ID_AA64FPFR0_EL1", "S3_0_C0_C4_7");
READ_ID_REG("ID_AA64DFR2_EL1", "S3_0_C0_C5_2");
READ_ID_REG("ID_AA64ISAR2_EL1", "S3_0_C0_C6_2");
READ_ID_REG("ID_AA64ISAR3_EL1", "S3_0_C0_C6_3");
READ_ID_REG("ID_AA64MMFR3_EL1", "S3_0_C0_C7_3");
READ_ID_REG("ID_AA64MMFR4_EL1", "S3_0_C0_C7_4");
READ_ID_REG("S3_0_C0_C7_7", "S3_0_C0_C7_7");
READ_ID_REG("TPIDRRO_EL0", "tpidrro_el0");
return 0;
}
Empty file.
13 changes: 13 additions & 0 deletions none/tests/arm64/mrs_id_regs.stdout.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
ID_ISAR0_EL1 0x0000000000000000
MVFR0_EL1 0x0000000000000000
ID_AA64PFR2_EL1 0x0000000000000000
ID_AA64ZFR0_EL1 0x0000000000000000
ID_AA64SMFR0_EL1 0x0000000000000000
ID_AA64FPFR0_EL1 0x0000000000000000
ID_AA64DFR2_EL1 0x0000000000000000
ID_AA64ISAR2_EL1 0x0000000000000000
ID_AA64ISAR3_EL1 0x0000000000000000
ID_AA64MMFR3_EL1 0x0000000000000000
ID_AA64MMFR4_EL1 0x0000000000000000
S3_0_C0_C7_7 0x0000000000000000
TPIDRRO_EL0 0x0000000000000000
2 changes: 2 additions & 0 deletions none/tests/arm64/mrs_id_regs.vgtest
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
prog: mrs_id_regs
vgopts: -q
Loading