From patchwork Wed Jul 27 11:26:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 72850 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp248489qga; Wed, 27 Jul 2016 04:26:13 -0700 (PDT) X-Received: by 10.98.70.8 with SMTP id t8mr48629481pfa.36.1469618773070; Wed, 27 Jul 2016 04:26:13 -0700 (PDT) Return-Path: Received: from ml01.01.org (ml01.01.org. [198.145.21.10]) by mx.google.com with ESMTPS id i8si6041233pfa.231.2016.07.27.04.26.12 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 27 Jul 2016 04:26:13 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) client-ip=198.145.21.10; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of edk2-devel-bounces@lists.01.org designates 198.145.21.10 as permitted sender) smtp.mailfrom=edk2-devel-bounces@lists.01.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 594511A1E10; Wed, 27 Jul 2016 04:26:12 -0700 (PDT) X-Original-To: edk2-devel@lists.01.org Delivered-To: edk2-devel@lists.01.org Received: from mail-wm0-x235.google.com (mail-wm0-x235.google.com [IPv6:2a00:1450:400c:c09::235]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 521E21A1E0F for ; Wed, 27 Jul 2016 04:26:11 -0700 (PDT) Received: by mail-wm0-x235.google.com with SMTP id i5so57513444wmg.0 for ; Wed, 27 Jul 2016 04:26:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=f6DX2PxsXWg9vrOV8CeNlMTbkPytRTKwGwQbTIfsZ9A=; b=huV06CWHZQ162n00nrgOFkul1ei1wxWmM6dwsI7/x9e3PlU8gRxcij/QeHm9IPHa/M MiHrH2+lriVSlE5ajUdDIvQjDCID68I16/32WqmB0D5JkHend378GQkVN6HJ6zwwP8y3 J/GdwoMNBlEOeTy5lBfEqeyF7MlV9h3I7ScGI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=f6DX2PxsXWg9vrOV8CeNlMTbkPytRTKwGwQbTIfsZ9A=; b=iEcXg0X+cbwe6i9sVb3K3fPvRQAQ1f7Np3tr4dO7+MJXGjOGuPHcZB/D4Nye9OILql VqpFkjtMAQhNmyfiFRFpSTNVsVrPuw45Ri1M8cUyEfzKTr78sk069voKE9jus90YNL+Q jFljTAN/Ypwyj1rHR5PwAy6A9B3LjbJVWiCoTEs28oPTxh0QPcQUp5UhW1UFPcb4HklZ LmzSxur4w4/ZBfxPhYQKnSCAiRvFvH2ykKs2wrA5/VB6CTMfn+VhL8ve45L0BE/Nq27C ldADskHNHBzS9W6F6GjpMlEpq+U1ENzr9GB8HEXfVPrIeSiZJkOZcyJgYe5QIoXzm9pS TcpA== X-Gm-Message-State: AEkooutYEHoa8H3IR84+UttD5wAe9q/u6GhTPI2VFrPkhP3MogzSAn8CAbsAEr/IOn7IeR/x X-Received: by 10.28.154.21 with SMTP id c21mr33038223wme.63.1469618769692; Wed, 27 Jul 2016 04:26:09 -0700 (PDT) Received: from localhost.localdomain (154.red-83-36-182.dynamicip.rima-tde.net. [83.36.182.154]) by smtp.gmail.com with ESMTPSA id 190sm6638401wmk.13.2016.07.27.04.26.07 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 27 Jul 2016 04:26:09 -0700 (PDT) From: Ard Biesheuvel To: edk2-devel@lists.01.org, liming.gao@intel.com, yonghong.zhu@intel.com Date: Wed, 27 Jul 2016 13:26:01 +0200 Message-Id: <1469618762-7648-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.7.4 Subject: [edk2] [PATCH 1/2] BaseTools/GenFw AARCH64: convert ADRP to ADR if binary size allows it X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel , leif.lindholm@linaro.org, eugene@hp.com MIME-Version: 1.0 Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" The ADRP instruction in the AArch64 ISA requires the link time and load time offsets of a binary to be equal modulo 4 KB. The reason is that this instruction always produces a multiple of 4 KB, and relies on a subsequent ADD or LDR instruction to set the offset into the page. The resulting symbol reference only produces the correct value if the symbol in question resides at that exact offset into the page, and so loading the binary at arbitrary offsets is not possible. Due to the various levels of padding when packing FVs into FVs into FDs, this alignment is very costly for XIP code, and so we would like to relax this alignment requirement if possible. Given that symbols that are sufficiently close (within 1 MB) of the reference can also be reached using an ADR instruction which does not suffer from this alignment issue, let's replace ADRP instructions with ADR after linking if the offset can be encoded in this instruction's immediate field. Note that this only makes sense if the section alignment is < 4 KB. Otherwise, replacing the ADRP has no benefit, considering that the subsequent ADD or LDR instruction is retained, and that micro-architectures are more likely to be optimized for ADRP/ADD pairs (i.e., via micro op fusing) than for ADR/ADD pairs, which are non-typical. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ard Biesheuvel --- BaseTools/Source/C/GenFw/Elf64Convert.c | 51 ++++++++++++++++---- 1 file changed, 42 insertions(+), 9 deletions(-) -- 2.7.4 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel Reviewed-by: Leif Lindholm diff --git a/BaseTools/Source/C/GenFw/Elf64Convert.c b/BaseTools/Source/C/GenFw/Elf64Convert.c index 024a2a0d5357..944c94b8f8b4 100644 --- a/BaseTools/Source/C/GenFw/Elf64Convert.c +++ b/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -806,26 +806,59 @@ WriteSections64 ( switch (ELF_R_TYPE(Rel->r_info)) { case R_AARCH64_ADR_PREL_PG_HI21: - case R_AARCH64_ADD_ABS_LO12_NC: - case R_AARCH64_LDST8_ABS_LO12_NC: - case R_AARCH64_LDST16_ABS_LO12_NC: - case R_AARCH64_LDST32_ABS_LO12_NC: - case R_AARCH64_LDST64_ABS_LO12_NC: - case R_AARCH64_LDST128_ABS_LO12_NC: // // AArch64 PG_H21 relocations are typically paired with ABS_LO12 // relocations, where a PC-relative reference with +/- 4 GB range is // split into a relative high part and an absolute low part. Since // the absolute low part represents the offset into a 4 KB page, we + // either have to convert the ADRP into an ADR instruction, or we + // need to use a section alignment of at least 4 KB, so that the + // binary appears at a correct offset at runtime. In any case, we // have to make sure that the 4 KB relative offsets of both the // section containing the reference as well as the section to which // it refers have not been changed during PE/COFF conversion (i.e., // in ScanSections64() above). // + if (mCoffAlignment < 0x1000) { + // + // Attempt to convert the ADRP into an ADR instruction. + // This is only possible if the symbol is within +/- 1 MB. + // + INT64 Offset; + + // Decode the ADRP instruction + Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8); + Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12)); + + // + // ADRP offset is relative to the previous page boundary, + // whereas ADR offset is relative to the instruction itself. + // So fix up the offset so it points to the page containing + // the symbol. + // + Offset -= (UINTN)(Targ - mCoffFile) & 0xfff; + + if (Offset < -0x100000 || Offset > 0xfffff) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.", + mInImageName); + break; + } + + // Re-encode the offset as an ADR instruction + *(UINT32 *)Targ &= 0x1000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + } + /* fall through */ + + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 || - ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0 || - mCoffAlignment < 0x1000) { - Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires 4 KB section alignment.", + ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.", mInImageName); break; }