Skip to content

Commit

Permalink
[ELF] Implement scanner for Cortex-A53 Erratum 843419
Browse files Browse the repository at this point in the history
 
Add a new file AArch64ErrataFix.cpp that implements the logic to scan for
the Cortex-A53 Erratum 843419. This involves finding all the executable
code, disassembling the instructions that might trigger the erratum and
reporting a message if the sequence is detected.

At this stage we do not attempt to fix the erratum, this functionality
will be added in a later patch. See D36749 for proposal.

Differential Revision: https://reviews.llvm.org/D36742

llvm-svn: 319780
  • Loading branch information
smithp35 committed Dec 5, 2017
1 parent fa40ee7 commit 732cd8c
Show file tree
Hide file tree
Showing 10 changed files with 886 additions and 3 deletions.
1 change: 1 addition & 0 deletions lld/ELF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ if(NOT LLD_BUILT_STANDALONE)
endif()

add_lld_library(lldELF
AArch64ErrataFix.cpp
Arch/AArch64.cpp
Arch/AMDGPU.cpp
Arch/ARM.cpp
Expand Down
1 change: 1 addition & 0 deletions lld/ELF/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ struct Configuration {
bool EmitRelocs;
bool EnableNewDtags;
bool ExportDynamic;
bool FixCortexA53Errata843419;
bool GcSections;
bool GdbIndex;
bool GnuHash = false;
Expand Down
4 changes: 4 additions & 0 deletions lld/ELF/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,9 @@ static void checkOptions(opt::InputArgList &Args) {
if (Config->EMachine == EM_MIPS && Config->GnuHash)
error("the .gnu.hash section is not compatible with the MIPS target.");

if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64)
error("--fix-cortex-a53-843419 is only supported on AArch64 targets.");

if (Config->Pie && Config->Shared)
error("-shared and -pie may not be used together");

Expand Down Expand Up @@ -610,6 +613,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
Config->FilterList = args::getStrings(Args, OPT_filter);
Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");
Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419);
Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
Config->ICF = Args.hasFlag(OPT_icf_all, OPT_icf_none, false);
Expand Down
3 changes: 3 additions & 0 deletions lld/ELF/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ defm filter: Eq<"filter">,
defm fini: Eq<"fini">,
HelpText<"Specify a finalizer function">, MetaVarName<"<symbol>">;

def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,
HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">;

def full_shutdown : F<"full-shutdown">,
HelpText<"Perform a full shutdown instead of calling _exit">;

Expand Down
14 changes: 11 additions & 3 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//

#include "Writer.h"
#include "AArch64ErrataFix.h"
#include "Config.h"
#include "Filesystem.h"
#include "LinkerScript.h"
Expand Down Expand Up @@ -1349,9 +1350,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!Script->HasSectionsCommand && !Config->Relocatable)
fixSectionAlignments();

// Some architectures use small displacements for jump instructions.
// It is linker's responsibility to create thunks containing long
// jump instructions if jump targets are too far. Create thunks.
// Some architectures need to generate content that depends on the address
// of InputSections. For example some architectures use small displacements
// for jump instructions that is is the linker's responsibility for creating
// range extension thunks for. As the generation of the content may also
// alter InputSection addresses we must converge to a fixed point.
if (Target->NeedsThunks || Config->AndroidPackDynRelocs) {
ThunkCreator TC;
bool Changed;
Expand All @@ -1360,6 +1363,11 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
Changed = false;
if (Target->NeedsThunks)
Changed |= TC.createThunks(OutputSections);
if (Config->FixCortexA53Errata843419) {
if (Changed)
Script->assignAddresses();
reportA53Errata843419Fixes();
}
if (InX::MipsGot)
InX::MipsGot->updateAllocSize();
Changed |= In<ELFT>::RelaDyn->updateAllocSize();
Expand Down
138 changes: 138 additions & 0 deletions lld/test/ELF/aarch64-cortex-a53-843419-address.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
// REQUIRES: aarch64
// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
// RUN: echo "SECTIONS { \
// RUN: .text : { *(.text) *(.text.*) *(.newisd) } \
// RUN: .text2 : { *.(newos) } \
// RUN: .data : { *(.data) } }" > %t.script
// RUN: ld.lld --script %t.script -fix-cortex-a53-843419 -verbose %t.o -o %t2 | FileCheck %s

// Test cases for Cortex-A53 Erratum 843419 that involve interactions
// between the generated patches and the address of sections

// See ARM-EPM-048406 Cortex_A53_MPCore_Software_Developers_Errata_Notice.pdf
// for full erratum details.
// In Summary
// 1.)
// ADRP (0xff8 or 0xffc)
// 2.)
// - load or store single register or either integer or vector registers
// - STP or STNP of either vector or vector registers
// - Advanced SIMD ST1 store instruction
// Must not write Rn
// 3.) optional instruction, can't be a branch, must not write Rn, may read Rn
// 4.) A load or store instruction from the Load/Store register unsigned
// immediate class using Rn as the base register

// An aarch64 section can contain ranges of literal data embedded within the
// code, these ranges are encoded with mapping symbols. This tests that we
// can match the erratum sequence in code, but not data
// - We can handle more than one patch per code range (denoted by mapping
// symbols)
// - We can handle a patch in more than range of code, with literal data
// inbetween
// - We can handle redundant mapping symbols (two or more consecutive mapping
// symbols with the same type)
// - We can ignore erratum sequences in multiple literal data ranges.

// CHECK: detected cortex-a53-843419 erratum sequence starting at FF8 in unpatched output.

.section .text.01, "ax", %progbits
.balign 4096
.space 4096 - 8
.globl t3_ff8_ldr
.type t3_ff8_ldr, %function
t3_ff8_ldr:
adrp x0, dat
ldr x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret


// create a redundant mapping symbol as we are already in a $x range
// some object producers unconditionally generate a mapping symbol on
// every symbol so we need to handle the case of $x $x
.local $x.999
$x.999:
// CHECK-NEXT: detected cortex-a53-843419 erratum sequence starting at 1FFC in unpatched output.
.globl t3_ffc_ldrsimd
.type t3_ffc_ldrsimd, %function
.space 4096 - 12
t3_ffc_ldrsimd:
adrp x0, dat
ldr s1, [x1, #0]
ldr x2, [x0, :got_lo12:dat]
ret

// Inline data containing bit pattern of erratum sequence, expect no patch
.globl t3_ffc_ldralldata
.type t3_ff8_ldralldata, %function
.space 4096 - 20
t3_ff8_ldralldata:
// 0x90000000 = adrp x0, #0
.byte 0x00
.byte 0x00
.byte 0x00
.byte 0x90
// 0xf9400021 = ldr x1, [x1]
.byte 0x21
.byte 0x00
.byte 0x40
.byte 0xf9
// 0xf9400000 = ldr x0, [x0]
.byte 0x00
.byte 0x00
.byte 0x40
.byte 0xf9
// Check that we can recognise the erratum sequence post literal data

// CHECK-NEXT: detected cortex-a53-843419 erratum sequence starting at 3FF8 in unpatched output.

.space 4096 - 12
.globl t3_ffc_ldr
.type t3_ffc_ldr, %function
t3_ffc_ldr:
adrp x0, dat
ldr x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret

.section .text.02, "ax", %progbits
.space 4096 - 12

// Start a new InputSectionDescription (see Linker Script) so the
// start address will be
// affected by any patches added to previous InputSectionDescription

// CHECK: detected cortex-a53-843419 erratum sequence starting at 4FFC in unpatched output.

.section .newisd, "ax", %progbits
.globl t3_ffc_str
.type t3_ffc_str, %function
t3_ffc_str:
adrp x0, dat
str x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
.space 4096 - 20

// CHECK: detected cortex-a53-843419 erratum sequence starting at 5FF8 in unpatched output.

// Start a new OutputSection (see Linker Script) so the
// start address will be
// affected by any patches added to previous InputSectionDescription
.section .newos, "ax", %progbits
.globl t3_ff8_str
.type t3_ff8_str, %function
t3_ff8_str:
adrp x0, dat
str x1, [x1, #0]
ldr x0, [x0, :got_lo12:dat]
ret
.globl _start
.type _start, %function
_start:
ret

.data
.globl dat
dat: .word 0
10 changes: 10 additions & 0 deletions lld/test/ELF/aarch64-cortex-a53-843419-cli.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
// RUN: not ld.lld %t -fix-cortex-a53-843419 -o %t2 2>&1 | FileCheck %s

// CHECK: --fix-cortex-a53-843419 is only supported on AArch64 targets.
.globl entry
.text
.quad 0
entry:
ret
Loading

0 comments on commit 732cd8c

Please sign in to comment.