-
Notifications
You must be signed in to change notification settings - Fork 15.4k
Description
After b326cb6, arm64 Linux kernel builds fail to boot on certain platforms (initially reported on LKML, downstream report). As this happens early in boot (before the serial driver) and the only platform I have access to is an FVP (so limited debug options), I was able to narrow this hang to a change in create_init_idmap() in arch/arm64/kernel/pi/map_range.c with the help of a hack patch to undo that change dynamically.
map_range.i.txt
map_range.unopt.ll.txt
good-map_range.opt.ll.txt
bad-map_range.opt.ll.txt
The diff of the optimized IR:
diff --git a/good-map_range.opt.ll.txt b/bad-map_range.opt.ll.txt
index 9eef147..e98844b 100644
--- a/good-map_range.opt.ll.txt
+++ b/bad-map_range.opt.ll.txt
@@ -141,23 +141,24 @@ entry:
%add = add i64 %0, 4096
store i64 %add, ptr %ptep, align 8
%1 = load i8, ptr @arm64_use_ng_mappings, align 1, !range !11, !noundef !12
- %loadedv = trunc nuw i8 %1 to i1
- %or = select i1 %loadedv, i64 2051, i64 3
- %2 = call i64 asm "mrs $0, tcr_el1", "=r"() #3, !srcloc !8
- %and.i = and i64 %2, 576460752303423488
+ %2 = zext nneg i8 %1 to i64
+ %cond = shl nuw nsw i64 %2, 11
+ %3 = call i64 asm "mrs $0, tcr_el1", "=r"() #3, !srcloc !8
+ %and.i = and i64 %3, 576460752303423488
%tobool.i.not = icmp eq i64 %and.i, 0
%cond1 = select i1 %tobool.i.not, i64 768, i64 0
- %or2 = or disjoint i64 %cond1, %or
- %or6 = or disjoint i64 %or2, 29273397577909248
- %or8 = or disjoint i64 %or2, 18014398509483136
+ %or = or disjoint i64 %cond1, %cond
+ %or6 = or disjoint i64 %or, 29273397577909251
+ %and = and i64 %or6, 18014398509485827
+ %or8 = or disjoint i64 %and, 128
%not = xor i64 %clrmask, -1
%and22 = and i64 %or8, %not
%and25 = and i64 %or6, %not
call void @map_range(ptr noundef nonnull %ptep, i64 noundef ptrtoint (ptr @_stext to i64), i64 noundef ptrtoint (ptr @__initdata_begin to i64), i64 noundef ptrtoint (ptr @_stext to i64), i64 %and22, i32 noundef 0, ptr noundef %pg_dir, i1 noundef false, i64 noundef 0) #4
call void @map_range(ptr noundef nonnull %ptep, i64 noundef ptrtoint (ptr @__initdata_begin to i64), i64 noundef ptrtoint (ptr @_end to i64), i64 noundef ptrtoint (ptr @__initdata_begin to i64), i64 %and25, i32 noundef 0, ptr noundef %pg_dir, i1 noundef false, i64 noundef 0) #4
- %3 = load i64, ptr %ptep, align 8
+ %4 = load i64, ptr %ptep, align 8
call void @llvm.lifetime.end.p0(i64 8, ptr nonnull %ptep) #5
- ret i64 %3
+ ret i64 %4
}
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
The object file diff:
diff --git a/tmp/.psub.9lwVS5WRhB b/tmp/.psub.RgCvbpYhdV
index 7c4d9d9..c046c52 100644
--- a/tmp/.psub.9lwVS5WRhB
+++ b/tmp/.psub.RgCvbpYhdV
@@ -1,5 +1,5 @@
-build/linux/good/arch/arm64/kernel/pi/map_range.o: file format elf64-littleaarch64
+build/linux/bad/arch/arm64/kernel/pi/map_range.o: file format elf64-littleaarch64
Disassembly of section .init.text:
@@ -128,52 +128,47 @@ create_init_idmap>:
d10103ff sub sp, sp, #0x40
90000008 adrp x8, 0x0 <map_range>
00000000000001dc: R_AARCH64_ADR_PREL_PG_HI21 arm64_use_ng_mappings
- 52810069 mov w9, #0x803 // =2051
- d538204a mrs x10, TCR_EL1
+ d5382049 mrs x9, TCR_EL1
+ f245013f tst x9, #0x800000000000000
39400108 ldrb w8, [x8]
00000000000001e8: R_AARCH64_LDST8_ABS_LO12_NC arm64_use_ng_mappings
- d280900b mov x11, #0x480 // =1152
+ 52806009 mov w9, #0x300 // =768
a90257f6 stp x22, x21, [sp, #0x20]
- f2e0080b movk x11, #0x40, lsl #48
+ 9a9f0129 csel x9, x9, xzr, eq
a9034ff4 stp x20, x19, [sp, #0x30]
aa0103f3 mov x19, x1
- 7100011f cmp w8, #0x0
- 52800068 mov w8, #0x3 // =3
+ aa082d28 orr x8, x9, x8, lsl #11
+ d2808069 mov x9, #0x403 // =1027
aa0003f4 mov x20, x0
- 9a881128 csel x8, x9, x8, ne
- f245015f tst x10, #0x800000000000000
- 52806009 mov w9, #0x300 // =768
- 9a9f0129 csel x9, x9, xzr, eq
+ f2e00d09 movk x9, #0x68, lsl #48
90000015 adrp x21, 0x0 <map_range>
- 000000000000021c: R_AARCH64_ADR_PREL_PG_HI21 __initdata_begin
+ 0000000000000210: R_AARCH64_ADR_PREL_PG_HI21 __initdata_begin
910002b5 add x21, x21, #0x0
- 0000000000000220: R_AARCH64_ADD_ABS_LO12_NC __initdata_begin
- aa080128 orr x8, x9, x8
- d2808009 mov x9, #0x400 // =1024
+ 0000000000000214: R_AARCH64_ADD_ABS_LO12_NC __initdata_begin
+ aa090116 orr x22, x8, x9
+ 91400408 add x8, x0, #0x1, lsl #12 // =0x1000
90000001 adrp x1, 0x0 <map_range>
- 000000000000022c: R_AARCH64_ADR_PREL_PG_HI21 _stext
+ 0000000000000220: R_AARCH64_ADR_PREL_PG_HI21 _stext
91000021 add x1, x1, #0x0
- 0000000000000230: R_AARCH64_ADD_ABS_LO12_NC _stext
- f2e00d09 movk x9, #0x68, lsl #48
- 9140040a add x10, x0, #0x1, lsl #12 // =0x1000
- aa090116 orr x22, x8, x9
- aa0b0108 orr x8, x8, x11
+ 0000000000000224: R_AARCH64_ADD_ABS_LO12_NC _stext
+ 924af2c9 and x9, x22, #0xffc7ffffffffffff
+ a90023ff stp xzr, x8, [sp]
+ b2790128 orr x8, x9, #0x80
910023e0 add x0, sp, #0x8
- 8a330104 bic x4, x8, x19
aa1503e2 mov x2, x21
+ 8a330104 bic x4, x8, x19
aa0103e3 mov x3, x1
2a1f03e5 mov w5, wzr
aa1403e6 mov x6, x20
2a1f03e7 mov w7, wzr
a9017bfd stp x29, x30, [sp, #0x10]
910043fd add x29, sp, #0x10
- a9002bff stp xzr, x10, [sp]
- 94000000 bl 0x26c <create_init_idmap+0x94>
- 000000000000026c: R_AARCH64_CALL26 map_range
+ 94000000 bl 0x258 <create_init_idmap+0x80>
+ 0000000000000258: R_AARCH64_CALL26 map_range
90000002 adrp x2, 0x0 <map_range>
- 0000000000000270: R_AARCH64_ADR_PREL_PG_HI21 _end
+ 000000000000025c: R_AARCH64_ADR_PREL_PG_HI21 _end
91000042 add x2, x2, #0x0
- 0000000000000274: R_AARCH64_ADD_ABS_LO12_NC _end
+ 0000000000000260: R_AARCH64_ADD_ABS_LO12_NC _end
910023e0 add x0, sp, #0x8
8a3302c4 bic x4, x22, x19
aa1503e1 mov x1, x21
@@ -182,8 +177,8 @@ create_init_idmap>:
aa1403e6 mov x6, x20
2a1f03e7 mov w7, wzr
f90003ff str xzr, [sp]
- 94000000 bl 0x298 <create_init_idmap+0xc0>
- 0000000000000298: R_AARCH64_CALL26 map_range
+ 94000000 bl 0x284 <create_init_idmap+0xac>
+ 0000000000000284: R_AARCH64_CALL26 map_range
a9434ff4 ldp x20, x19, [sp, #0x30]
f94007e0 ldr x0, [sp, #0x8]
a94257f6 ldp x22, x21, [sp, #0x20]
If I replace arch/arm64/kernel/pi/map_range.o by running llc --filetype obj on either the good optimized IR or the unoptimized IR, the kernel boots fine. As soon as I use the bad optimized IR, there is a hang. My initial suspicion is that PAGE_KERNEL_ROX is not getting optimized correctly but my assembly knowledge is not very good so I might be misunderstanding something.
The command to generate the .o from the .i if necessary.
clang --target=aarch64-linux-gnu -fintegrated-as -mlittle-endian -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -mgeneral-regs-only -Wno-psabi -fno-asynchronous-unwind-tables -fno-unwind-tables -mbranch-protection=pac-ret+bti -Wa,-march=armv8.5-a -fno-delete-null-pointer-checks -O2 -fstack-protector-strong -fno-omit-frame-pointer -fno-optimize-sibling-calls -ftrivial-auto-var-init=zero -fno-stack-clash-protection -falign-functions=4 -fstrict-flex-arrays=3 -fno-strict-overflow -fno-stack-check -fno-builtin-wcslen -Wall -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=2048 -Wno-gnu -Wno-format-overflow-non-kprintf -Wno-format-truncation-non-kprintf -Wvla -Wno-pointer-sign -Wcast-function-type -Wimplicit-fallthrough -Werror=date-time -Werror=incompatible-pointer-types-Wenum-conversion -Wextra -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-format-overflow -Wno-override-init -Wno-pointer-to-enum-cast -Wno-tautological-constant-out-of-range-compare -Wno-unaligned-access -Wno-enum-compare-conditional -Wno-missing-field-initializers -Wno-type-limits -Wno-shift-negative-value -Wno-enum-enum-conversion -Wno-sign-compare -Wno-unused-parameter -mstack-protector-guard=sysreg -mstack-protector-guard-reg=sp_el0 -mstack-protector-guard-offset=1240 -fpie -Os -mbranch-protection=none -fno-stack-protector -ffreestanding -fno-asynchronous-unwind-tables -fno-unwind-tables -fno-addrsig -mstrict-align -c map_range.i
Please feel free to give this issue a more descriptive title if necessary.