From de8c3582d2eb280bf6b358349e04a959b945f1a5 Mon Sep 17 00:00:00 2001 From: Peter Jones Date: Fri, 1 Jul 2022 15:52:51 -0400 Subject: [PATCH] aarch64: Keep _relocate() from being dirtied by _relocate() [Patch is a gnu-efi patch we apply to the bundled copy.] This could all be wrong, but the fix seems to work. Here's my theory of what's going on. We have a bug report that says: No EFI system partition Booting /efi\boot\bootaa64.efi No EFI system partition Failed to persist EFI variables "Synchronous Abort" handler, esr 0x02000000 elr: fffffffffeb48a28 lr : fffffffffeb3f024 (reloc) elr: 000000003ca1aa28 lr : 000000003ca11024 x0 : 000000003ca0d000 x1 : 000000003ca22018 x2 : 000000003ca22000 x3 : 0000000000000018 x4 : 0000000000001488 x5 : 0000000000000000 x6 : 0000000000001000 x7 : 0000000000000000 x8 : 0000000000000007 x9 : 0000000000003ca0 x10: 000000003ca3e040 x11: 00000000b0b87665 x12: 000000007c70ea25 x13: 000000005a827999 x14: 000000006ed9eba1 x15: 000000008f1bbcdc x16: 000000003df97394 x17: 00000000b7ce40b7 x18: 0000000000000011 x19: 000000003caeb000 x20: 0000000000000000 x21: 000000003dc1ba50 x22: 000000003caff2f8 x23: 0000000000000001 x24: 000000003caff000 x25: 000000003caff3c0 x26: 000000003caff3c8 x27: 000000003caff3d0 x28: 000000003caff3d8 x29: 000000003db3e600 Code: 8b000021 f82068a1 8b030042 cb030084 (f100009f) UEFI image [0x000000003ca0d000:0x000000003ca24fff] pc=0xda28 '/efi\boot\fbaa64.efi' Resetting CPU ... resetting ... When I disassemble it, "8b000021 f82068a1 8b030042 cb030084 (f100009f)" at 0xda28 (aka 0x3ca1aa28 in our register dump above) is: da18: 8b000021 add x1, x1, x0 da1c: f82068a1 str x1, [x5, x0] da20: 8b030042 add x2, x2, x3 da24: cb030084 sub x4, x4, x3 da28: f100009f cmp x4, #0x0 Of course the Arm ARM says "cmp" cannot fault in this way, and %esr is less than helpful, for reasons I don't understand. I believe what is happening is this. Farther up in the file is the function StatusToString(), as seen here: 000000000000d960 : d960: d0000022 adrp x2, 13000 d964: aa0103e3 mov x3, x1 d968: 911f0042 add x2, x2, #0x7c0 d96c: f9400441 ldr x1, [x2, #8] d970: b5000081 cbnz x1, d980 d974: b0000022 adrp x2, 12000 d978: 91124842 add x2, x2, #0x492 d97c: 17fffc32 b ca44 d980: f8410444 ldr x4, [x2], #16 d984: eb03009f cmp x4, x3 d988: 54ffff21 b.ne d96c // b.any d98c: 17fffe47 b d2a8 I believe when _relocate() gets to the relocations for 0xd960 the page being processed is evicted from the i$ and moved into the d$, and then when execution continues, the i$ raises an exception because it doesn't have the page in question, and it can't stall execution to fill it, because it's now owned (and dirty) in the other cache. There are a couple of ways to solve this, but I've taken the laziest one: align the code in _relocate() to its own page boundary. This partially works because our link order means this code is actually the last function in .text, and so no relocations will ever land on this page. Signed-off-by: Peter Jones [rharwood@redhat.com: adapt to shim] Signed-off-by: Robbie Harwood --- gnu-efi/gnuefi/reloc_aarch64.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gnu-efi/gnuefi/reloc_aarch64.c b/gnu-efi/gnuefi/reloc_aarch64.c index 086727961c2..0022abdaca7 100644 --- a/gnu-efi/gnuefi/reloc_aarch64.c +++ b/gnu-efi/gnuefi/reloc_aarch64.c @@ -48,6 +48,11 @@ EFI_STATUS _relocate (long ldbase, Elf64_Dyn *dyn, unsigned long *addr; int i; + /* + * We need this code to not be on the same page as any relocations. + */ + __asm__(".balign 4096\n"); + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { switch (dyn[i].d_tag) { case DT_RELA: -- 2.35.1