summaryrefslogtreecommitdiff
path: root/arch/arm64
diff options
context:
space:
mode:
authorEmil Renner Berthing <kernel@esmil.dk>2022-02-23 20:12:57 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2022-03-16 13:21:48 +0100
commit978e4f2648c1b73115cad866c29b9376e58a3419 (patch)
tree341c18bd5d33461f22b8222eb37c08e4c540a995 /arch/arm64
parentd6948de3b6302d6587a1acab2c912c3a988f0910 (diff)
riscv: Fix auipc+jalr relocation range checks
commit 0966d385830de3470b7131db8e86c0c5bc9c52dc upstream. RISC-V can do PC-relative jumps with a 32bit range using the following two instructions: auipc t0, imm20 ; t0 = PC + imm20 * 2^12 jalr ra, t0, imm12 ; ra = PC + 4, PC = t0 + imm12 Crucially both the 20bit immediate imm20 and the 12bit immediate imm12 are treated as two's-complement signed values. For this reason the immediates are usually calculated like this: imm20 = (offset + 0x800) >> 12 imm12 = offset & 0xfff ..where offset is the signed offset from the auipc instruction. When the 11th bit of offset is 0 the addition of 0x800 doesn't change the top 20 bits and imm12 considered positive. When the 11th bit is 1 the carry of the addition by 0x800 means imm20 is one higher, but since imm12 is then considered negative the two's complement representation means it all cancels out nicely. However, this addition by 0x800 (2^11) means an offset greater than or equal to 2^31 - 2^11 would overflow so imm20 is considered negative and result in a backwards jump. Similarly the lower range of offset is also moved down by 2^11 and hence the true 32bit range is [-2^31 - 2^11, 2^31 - 2^11) Signed-off-by: Emil Renner Berthing <kernel@esmil.dk> Fixes: e2c0cdfba7f6 ("RISC-V: User-facing API") Cc: stable@vger.kernel.org Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'arch/arm64')
0 files changed, 0 insertions, 0 deletions