Build Linux 5.10 LTS for Phicomm N1Recently I built Linux 5.10 LTS for my N1 box. Below are the patches I needed during the building process.
TEXT_OFFSET
Obsolete: See comments from justin below, it’s no longer necessary to do this. Chainloading u-boot allows you to boot the kernel without this patch.
Due to some quirks in U-boot shipped with N1, we need to apply an offset on TEXT_OFFSET
of bootloader. In the past we did this simply by changing arch/arm64/Makefile
. However, TEXT_OFFSET
is completely removed from Linux 5.8+.
For this matter, I simply reverted that commit.
Here’s the patch for reverting the commit:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 diff -uNr a/arch/arm64/Makefile b/arch/arm64/Makefile--- a/arch/arm64/Makefile 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/Makefile 2021-09-01 13:40:07.248858059 +0800@@ -11,6 +11,7 @@ # Copyright (C) 1995-2001 by Russell King LDFLAGS_vmlinux :=--no-undefined -X+CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) ifeq ($(CONFIG_RELOCATABLE), y) # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour@@ -134,6 +135,9 @@ # Default value head-y := arch/arm64/kernel/head.o +# The byte offset of the kernel image in RAM from the start of RAM.+TEXT_OFFSET := 0x01080000+ ifeq ($(CONFIG_KASAN_SW_TAGS), y) KASAN_SHADOW_SCALE_SHIFT := 4 else@@ -144,6 +148,8 @@ KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) +export TEXT_OFFSET+ core-y += arch/arm64/ libs-y := arch/arm64/lib/ $(libs-y) libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.adiff -uNr a/arch/arm64/include/asm/boot.h b/arch/arm64/include/asm/boot.h--- a/arch/arm64/include/asm/boot.h 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/include/asm/boot.h 2021-09-01 13:40:07.248858059 +0800@@ -13,7 +13,8 @@ #define MAX_FDT_SIZE SZ_2M /*- * arm64 requires the kernel image to placed at a 2 MB aligned base address+ * arm64 requires the kernel image to placed+ * TEXT_OFFSET bytes beyond a 2 MB aligned base */ #define MIN_KIMG_ALIGN SZ_2M diff -uNr a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h--- a/arch/arm64/include/asm/kernel-pgtable.h 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/include/asm/kernel-pgtable.h 2021-09-01 13:40:07.248858059 +0800@@ -86,7 +86,7 @@ + EARLY_PGDS((vstart), (vend)) /* each PGDIR needs a next level page table */ \ + EARLY_PUDS((vstart), (vend)) /* each PUD needs a next level page table */ \ + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */-#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end))+#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR + TEXT_OFFSET, _end)) #define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE) /* Initial memory map size */diff -uNr a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h--- a/arch/arm64/include/asm/memory.h 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/include/asm/memory.h 2021-09-01 13:40:07.248858059 +0800@@ -173,7 +173,7 @@ /* PHYS_OFFSET - the physical address of the start of memory. */ #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) -/* the virtual base of the kernel image */+/* the virtual base of the kernel image (minus TEXT_OFFSET) */ extern u64 kimage_vaddr; /* the offset between the kernel virtual and physical mappings */diff -uNr a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile--- a/arch/arm64/kernel/Makefile 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/kernel/Makefile 2021-09-01 13:40:07.248858059 +0800@@ -3,6 +3,8 @@ # Makefile for the linux kernel. # +CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET)+AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_armv8_deprecated.o := -I$(src) CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE)diff -uNr a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S--- a/arch/arm64/kernel/head.S 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/kernel/head.S 2021-09-01 13:41:15.870790059 +0800@@ -36,10 +36,14 @@ #include "efi-header.S" -#define __PHYS_OFFSET KERNEL_START+#define __PHYS_OFFSET (KERNEL_START - TEXT_OFFSET) -#if (PAGE_OFFSET & 0x1fffff) != 0+#if (TEXT_OFFSET & 0xfff) != 0+#error TEXT_OFFSET must be at least 4KB aligned+#elif (PAGE_OFFSET & 0x1fffff) != 0 #error PAGE_OFFSET must be at least 2MB aligned+#elif TEXT_OFFSET > 0x1fffff+//#error TEXT_OFFSET must be less than 2MB #endif /*@@ -73,7 +77,7 @@ b primary_entry // branch to kernel start, magic .long 0 // reserved #endif- .quad 0 // Image load offset from start of RAM, little-endian+ le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian le64sym _kernel_size_le // Effective size of kernel image, little-endian le64sym _kernel_flags_le // Informative flags, little-endian .quad 0 // reserved@@ -378,7 +382,7 @@ * Map the kernel image (starting with PHYS_OFFSET). */ adrp x0, init_pg_dir- mov_q x5, KIMAGE_VADDR // compile time __va(_text)+ mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) add x5, x5, x23 // add KASLR displacement mov x4, PTRS_PER_PGD adrp x6, _end // runtime __pa(_end)@@ -470,7 +474,7 @@ .pushsection ".rodata", "a" SYM_DATA_START(kimage_vaddr)- .quad _text+ .quad _text - TEXT_OFFSET SYM_DATA_END(kimage_vaddr) EXPORT_SYMBOL(kimage_vaddr) .popsectiondiff -uNr a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h--- a/arch/arm64/kernel/image.h 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/kernel/image.h 2021-09-01 13:40:07.248858059 +0800@@ -62,6 +62,7 @@ */ #define HEAD_SYMBOLS \ DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \+ DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); #endif /* __ARM64_KERNEL_IMAGE_H */diff -uNr a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S--- a/arch/arm64/kernel/vmlinux.lds.S 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/kernel/vmlinux.lds.S 2021-09-01 13:41:56.590790059 +0800@@ -115,7 +115,7 @@ *(.dynsym .dynstr .hash .gnu.hash) } - . = KIMAGE_VADDR;+ . = KIMAGE_VADDR + TEXT_OFFSET; .head.text : { _text = .;@@ -305,4 +305,4 @@ /* * If padding is applied before .head.text, virt<->phys conversions will fail. */-ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned")+ASSERT(_text == (KIMAGE_VADDR + TEXT_OFFSET), "HEAD is misaligned")diff -uNr a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile--- a/drivers/firmware/efi/libstub/Makefile 2021-08-26 20:51:21.000000000 +0800+++ b/drivers/firmware/efi/libstub/Makefile 2021-09-01 13:40:07.248858059 +0800@@ -69,6 +69,7 @@ lib-$(CONFIG_X86) += x86-stub.o lib-$(CONFIG_RISCV) += riscv-stub.o CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET)+CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) # Even when -mbranch-protection=none is set, Clang will generate a # .note.gnu.property for code-less object files (like lib/ctype.c),diff -uNr a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c--- a/drivers/firmware/efi/libstub/arm64-stub.c 2021-08-26 20:51:21.000000000 +0800+++ b/drivers/firmware/efi/libstub/arm64-stub.c 2021-09-01 13:50:44.710790059 +0800@@ -125,7 +125,7 @@ kernel_size = _edata - _text; kernel_memsize = kernel_size + (_end - _edata);- *reserve_size = kernel_memsize;+ *reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align; if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) { /*@@ -141,7 +141,7 @@ if (status != EFI_SUCCESS) { if (!check_image_region((u64)_text, kernel_memsize)) { efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n");- } else if (IS_ALIGNED((u64)_text, min_kimg_align)) {+ } else if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) { /* * Just execute from wherever we were loaded by the * UEFI PE/COFF loader if the alignment is suitable.@@ -161,7 +161,7 @@ } } - *image_addr = *reserve_addr;+ *image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align; memcpy((void *)*image_addr, _text, kernel_size); return EFI_SUCCESS;
N1-specific
I rebased most of the patches I used for Linux 5.0 to Linux 5.10 and applied them, with the exception of the patch regarding to RTL8211F ethernet PHY.
Interrupt for RTL8211F was originally marked as IRQ_TYPE_LEVEL_LOW
. Although it does work to some extent, it keeps burn CPU. From my guess the wrongly-marked IRQ type confused the kernel to believe an IRQ is keep firing. The net result is effectively a busy-polling.
So I marked the interrupt IRQ_TYPE_LEVEL_HIGH
when building Linux 5.10. The change might be wrong yet it worked well at that time.
However, on Linux 5.10, that patch no longer works. The NIC does not respond to packets at all. I tried all other IRQ types (rising-edge, failing-edge), and none of them works cleanly. Yes IRQ_TYPE_EDGE_BOTH
does appear to work, but if you check to see output of dmesg
you’d know it’s not “clean” at all.
After some testing, I totally removed the interrupts
node, and things works just fine. Presumbly Linux in this case falls back to do polling, in an adaquate interval or something. Not as good as interrupt-driven, yet much better than busy-polling. Besides, I see no visible CPU burns when the box is idle. That’s a “good enough” solution for me.
Another issue with Linux 5.10 was that block device name is no longer stable across reboot, I believed it had something to do with sd_emmc_b
. Since N1 do not support SD-card, so I disabled it in device tree.
And here is the patch:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960 diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi--- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-09-03 20:11:15.702744555 +0800@@ -275,7 +275,7 @@ /* SD card */ &sd_emmc_b {- status = "okay";+ status = "disabled"; pinctrl-0 = <&sdcard_pins>; pinctrl-1 = <&sdcard_clk_gate_pins>; pinctrl-names = "default", "clk-gate";@@ -300,7 +300,7 @@ bus-width = <8>; cap-mmc-highspeed;- max-frequency = <200000000>;+ max-frequency = <100000000>; non-removable; disable-wp; mmc-ddr-1_8v;diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi--- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2021-09-03 20:11:15.702744555 +0800@@ -25,9 +25,10 @@ #size-cells = <2>; ranges; - /* 16 MiB reserved for Hardware ROM Firmware */+ /* 1 MiB reserved for Hardware ROM Firmware */+ /* @sa: https://github.com/khadas/linux/commit/698df2c6cfbb0d1a9359743208e83517b31da6ce */ hwrom_reserved: hwrom@0 {- reg = <0x0 0x0 0x0 0x1000000>;+ reg = <0x0 0x0 0x0 0x100000>; no-map; }; diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts--- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2021-09-03 20:24:15.998685555 +0800@@ -86,8 +86,6 @@ reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; interrupt-parent = <&gpio_intc>;- interrupts = <29 IRQ_TYPE_LEVEL_LOW>;- eee-broken-1000t; }; }; diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi--- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2021-09-03 20:11:15.702744555 +0800@@ -51,6 +51,8 @@ dr_mode = "host"; maximum-speed = "high-speed"; snps,dis_u2_susphy_quirk;+ /* Workaround for broken LPM implementation found in many USB3 devices. */+ usb2-lpm-disable; }; };
Misc
Just as before, since I’m using the box headlessly, I repurposed frame-buffer for general use by Linux. Apply this patch only if you don’t need video output.
Note that this patch does not affect console output once Linux is fully booted, not sure the reason though.
123456789 --- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-08-26 20:51:21.000000000 +0800+++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-09-01 14:36:40.368207059 +0800@@ -36,6 +36,7 @@ memory@0 { device_type = "memory";+ linux,usable-memory = <0x0 0x0 0x0 0x80000000>; reg = <0x0 0x0 0x0 0x80000000>; };
End note
You can also download the patches here.
Recently I built Linux 5.10 LTS for my N1 box. Below are the patches I needed during the building process.
TEXT_OFFSET
Obsolete: See comments from justin below, it’s no longer necessary to do this. Chainloading u-boot allows you to boot the kernel without this patch.
Due to some quirks in U-boot shipped with N1, we need to apply an offset on TEXT_OFFSET
of bootloader. In the past we did this simply by changing arch/arm64/Makefile
. However, TEXT_OFFSET
is completely removed from Linux 5.8+.
For this matter, I simply reverted that commit.
Here’s the patch for reverting the commit:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | diff -uNr a/arch/arm64/Makefile b/arch/arm64/Makefile --- a/arch/arm64/Makefile 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/Makefile 2021-09-01 13:40:07.248858059 +0800 @@ -11,6 +11,7 @@ # Copyright (C) 1995-2001 by Russell King LDFLAGS_vmlinux :=--no-undefined -X +CPPFLAGS_vmlinux.lds = -DTEXT_OFFSET=$(TEXT_OFFSET) ifeq ($(CONFIG_RELOCATABLE), y) # Pass --no-apply-dynamic-relocs to restore pre-binutils-2.27 behaviour @@ -134,6 +135,9 @@ # Default value head-y := arch/arm64/kernel/head.o +# The byte offset of the kernel image in RAM from the start of RAM. +TEXT_OFFSET := 0x01080000 + ifeq ($(CONFIG_KASAN_SW_TAGS), y) KASAN_SHADOW_SCALE_SHIFT := 4 else @@ -144,6 +148,8 @@ KBUILD_CPPFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) KBUILD_AFLAGS += -DKASAN_SHADOW_SCALE_SHIFT=$(KASAN_SHADOW_SCALE_SHIFT) +export TEXT_OFFSET + core-y += arch/arm64/ libs-y := arch/arm64/lib/ $(libs-y) libs-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a diff -uNr a/arch/arm64/include/asm/boot.h b/arch/arm64/include/asm/boot.h --- a/arch/arm64/include/asm/boot.h 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/include/asm/boot.h 2021-09-01 13:40:07.248858059 +0800 @@ -13,7 +13,8 @@ #define MAX_FDT_SIZE SZ_2M /* - * arm64 requires the kernel image to placed at a 2 MB aligned base address + * arm64 requires the kernel image to placed + * TEXT_OFFSET bytes beyond a 2 MB aligned base */ #define MIN_KIMG_ALIGN SZ_2M diff -uNr a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h --- a/arch/arm64/include/asm/kernel-pgtable.h 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/include/asm/kernel-pgtable.h 2021-09-01 13:40:07.248858059 +0800 @@ -86,7 +86,7 @@ + EARLY_PGDS((vstart), (vend)) /* each PGDIR needs a next level page table */ \ + EARLY_PUDS((vstart), (vend)) /* each PUD needs a next level page table */ \ + EARLY_PMDS((vstart), (vend))) /* each PMD needs a next level page table */ -#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR, _end)) +#define INIT_DIR_SIZE (PAGE_SIZE * EARLY_PAGES(KIMAGE_VADDR + TEXT_OFFSET, _end)) #define IDMAP_DIR_SIZE (IDMAP_PGTABLE_LEVELS * PAGE_SIZE) /* Initial memory map size */ diff -uNr a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h --- a/arch/arm64/include/asm/memory.h 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/include/asm/memory.h 2021-09-01 13:40:07.248858059 +0800 @@ -173,7 +173,7 @@ /* PHYS_OFFSET - the physical address of the start of memory. */ #define PHYS_OFFSET ({ VM_BUG_ON(memstart_addr & 1); memstart_addr; }) -/* the virtual base of the kernel image */ +/* the virtual base of the kernel image (minus TEXT_OFFSET) */ extern u64 kimage_vaddr; /* the offset between the kernel virtual and physical mappings */ diff -uNr a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile --- a/arch/arm64/kernel/Makefile 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/kernel/Makefile 2021-09-01 13:40:07.248858059 +0800 @@ -3,6 +3,8 @@ # Makefile for the linux kernel. # +CPPFLAGS_vmlinux.lds := -DTEXT_OFFSET=$(TEXT_OFFSET) +AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) CFLAGS_armv8_deprecated.o := -I$(src) CFLAGS_REMOVE_ftrace.o = $(CC_FLAGS_FTRACE) diff -uNr a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S --- a/arch/arm64/kernel/head.S 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/kernel/head.S 2021-09-01 13:41:15.870790059 +0800 @@ -36,10 +36,14 @@ #include "efi-header.S" -#define __PHYS_OFFSET KERNEL_START +#define __PHYS_OFFSET (KERNEL_START - TEXT_OFFSET) -#if (PAGE_OFFSET & 0x1fffff) != 0 +#if (TEXT_OFFSET & 0xfff) != 0 +#error TEXT_OFFSET must be at least 4KB aligned +#elif (PAGE_OFFSET & 0x1fffff) != 0 #error PAGE_OFFSET must be at least 2MB aligned +#elif TEXT_OFFSET > 0x1fffff +//#error TEXT_OFFSET must be less than 2MB #endif /* @@ -73,7 +77,7 @@ b primary_entry // branch to kernel start, magic .long 0 // reserved #endif - .quad 0 // Image load offset from start of RAM, little-endian + le64sym _kernel_offset_le // Image load offset from start of RAM, little-endian le64sym _kernel_size_le // Effective size of kernel image, little-endian le64sym _kernel_flags_le // Informative flags, little-endian .quad 0 // reserved @@ -378,7 +382,7 @@ * Map the kernel image (starting with PHYS_OFFSET). */ adrp x0, init_pg_dir - mov_q x5, KIMAGE_VADDR // compile time __va(_text) + mov_q x5, KIMAGE_VADDR + TEXT_OFFSET // compile time __va(_text) add x5, x5, x23 // add KASLR displacement mov x4, PTRS_PER_PGD adrp x6, _end // runtime __pa(_end) @@ -470,7 +474,7 @@ .pushsection ".rodata", "a" SYM_DATA_START(kimage_vaddr) - .quad _text + .quad _text - TEXT_OFFSET SYM_DATA_END(kimage_vaddr) EXPORT_SYMBOL(kimage_vaddr) .popsection diff -uNr a/arch/arm64/kernel/image.h b/arch/arm64/kernel/image.h --- a/arch/arm64/kernel/image.h 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/kernel/image.h 2021-09-01 13:40:07.248858059 +0800 @@ -62,6 +62,7 @@ */ #define HEAD_SYMBOLS \ DEFINE_IMAGE_LE64(_kernel_size_le, _end - _text); \ + DEFINE_IMAGE_LE64(_kernel_offset_le, TEXT_OFFSET); \ DEFINE_IMAGE_LE64(_kernel_flags_le, __HEAD_FLAGS); #endif /* __ARM64_KERNEL_IMAGE_H */ diff -uNr a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S --- a/arch/arm64/kernel/vmlinux.lds.S 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/kernel/vmlinux.lds.S 2021-09-01 13:41:56.590790059 +0800 @@ -115,7 +115,7 @@ *(.dynsym .dynstr .hash .gnu.hash) } - . = KIMAGE_VADDR; + . = KIMAGE_VADDR + TEXT_OFFSET; .head.text : { _text = .; @@ -305,4 +305,4 @@ /* * If padding is applied before .head.text, virt<->phys conversions will fail. */ -ASSERT(_text == KIMAGE_VADDR, "HEAD is misaligned") +ASSERT(_text == (KIMAGE_VADDR + TEXT_OFFSET), "HEAD is misaligned") diff -uNr a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile --- a/drivers/firmware/efi/libstub/Makefile 2021-08-26 20:51:21.000000000 +0800 +++ b/drivers/firmware/efi/libstub/Makefile 2021-09-01 13:40:07.248858059 +0800 @@ -69,6 +69,7 @@ lib-$(CONFIG_X86) += x86-stub.o lib-$(CONFIG_RISCV) += riscv-stub.o CFLAGS_arm32-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +CFLAGS_arm64-stub.o := -DTEXT_OFFSET=$(TEXT_OFFSET) # Even when -mbranch-protection=none is set, Clang will generate a # .note.gnu.property for code-less object files (like lib/ctype.c), diff -uNr a/drivers/firmware/efi/libstub/arm64-stub.c b/drivers/firmware/efi/libstub/arm64-stub.c --- a/drivers/firmware/efi/libstub/arm64-stub.c 2021-08-26 20:51:21.000000000 +0800 +++ b/drivers/firmware/efi/libstub/arm64-stub.c 2021-09-01 13:50:44.710790059 +0800 @@ -125,7 +125,7 @@ kernel_size = _edata - _text; kernel_memsize = kernel_size + (_end - _edata); - *reserve_size = kernel_memsize; + *reserve_size = kernel_memsize + TEXT_OFFSET % min_kimg_align; if (IS_ENABLED(CONFIG_RANDOMIZE_BASE) && phys_seed != 0) { /* @@ -141,7 +141,7 @@ if (status != EFI_SUCCESS) { if (!check_image_region((u64)_text, kernel_memsize)) { efi_err("FIRMWARE BUG: Image BSS overlaps adjacent EFI memory region\n"); - } else if (IS_ALIGNED((u64)_text, min_kimg_align)) { + } else if (IS_ALIGNED((u64)_text - TEXT_OFFSET, min_kimg_align)) { /* * Just execute from wherever we were loaded by the * UEFI PE/COFF loader if the alignment is suitable. @@ -161,7 +161,7 @@ } } - *image_addr = *reserve_addr; + *image_addr = *reserve_addr + TEXT_OFFSET % min_kimg_align; memcpy((void *)*image_addr, _text, kernel_size); return EFI_SUCCESS; |
N1-specific
I rebased most of the patches I used for Linux 5.0 to Linux 5.10 and applied them, with the exception of the patch regarding to RTL8211F ethernet PHY.
Interrupt for RTL8211F was originally marked as IRQ_TYPE_LEVEL_LOW
. Although it does work to some extent, it keeps burn CPU. From my guess the wrongly-marked IRQ type confused the kernel to believe an IRQ is keep firing. The net result is effectively a busy-polling.
So I marked the interrupt IRQ_TYPE_LEVEL_HIGH
when building Linux 5.10. The change might be wrong yet it worked well at that time.
However, on Linux 5.10, that patch no longer works. The NIC does not respond to packets at all. I tried all other IRQ types (rising-edge, failing-edge), and none of them works cleanly. Yes IRQ_TYPE_EDGE_BOTH
does appear to work, but if you check to see output of dmesg
you’d know it’s not “clean” at all.
After some testing, I totally removed the interrupts
node, and things works just fine. Presumbly Linux in this case falls back to do polling, in an adaquate interval or something. Not as good as interrupt-driven, yet much better than busy-polling. Besides, I see no visible CPU burns when the box is idle. That’s a “good enough” solution for me.
Another issue with Linux 5.10 was that block device name is no longer stable across reboot, I believed it had something to do with sd_emmc_b
. Since N1 do not support SD-card, so I disabled it in device tree.
And here is the patch:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi --- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-09-03 20:11:15.702744555 +0800 @@ -275,7 +275,7 @@ /* SD card */ &sd_emmc_b { - status = "okay"; + status = "disabled"; pinctrl-0 = <&sdcard_pins>; pinctrl-1 = <&sdcard_clk_gate_pins>; pinctrl-names = "default", "clk-gate"; @@ -300,7 +300,7 @@ bus-width = <8>; cap-mmc-highspeed; - max-frequency = <200000000>; + max-frequency = <100000000>; non-removable; disable-wp; mmc-ddr-1_8v; diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi --- a/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/boot/dts/amlogic/meson-gx.dtsi 2021-09-03 20:11:15.702744555 +0800 @@ -25,9 +25,10 @@ #size-cells = <2>; ranges; - /* 16 MiB reserved for Hardware ROM Firmware */ + /* 1 MiB reserved for Hardware ROM Firmware */ + /* @sa: https://github.com/khadas/linux/commit/698df2c6cfbb0d1a9359743208e83517b31da6ce */ hwrom_reserved: hwrom@0 { - reg = <0x0 0x0 0x0 0x1000000>; + reg = <0x0 0x0 0x0 0x100000>; no-map; }; diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts --- a/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts 2021-09-03 20:24:15.998685555 +0800 @@ -86,8 +86,6 @@ reset-gpios = <&gpio GPIOZ_14 GPIO_ACTIVE_LOW>; interrupt-parent = <&gpio_intc>; - interrupts = <29 IRQ_TYPE_LEVEL_LOW>; - eee-broken-1000t; }; }; diff -uNr a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi --- a/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/boot/dts/amlogic/meson-gxl.dtsi 2021-09-03 20:11:15.702744555 +0800 @@ -51,6 +51,8 @@ dr_mode = "host"; maximum-speed = "high-speed"; snps,dis_u2_susphy_quirk; + /* Workaround for broken LPM implementation found in many USB3 devices. */ + usb2-lpm-disable; }; }; |
Misc
Just as before, since I’m using the box headlessly, I repurposed frame-buffer for general use by Linux. Apply this patch only if you don’t need video output.
Note that this patch does not affect console output once Linux is fully booted, not sure the reason though.
1 2 3 4 5 6 7 8 9 | --- a/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-08-26 20:51:21.000000000 +0800 +++ b/arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi 2021-09-01 14:36:40.368207059 +0800 @@ -36,6 +36,7 @@ memory@0 { device_type = "memory"; + linux,usable-memory = <0x0 0x0 0x0 0x80000000>; reg = <0x0 0x0 0x0 0x80000000>; }; |
End note
You can also download the patches here.
there is a new uboot for n1, you don’t need text_offset patch anymore, tested 5.10.x and 5.15.x
https://github.com/cattyhouse/new-uboot-for-N1
https://github.com/cattyhouse/N1-install#挂载-u-boot
Chainloading u-boot really is an interesting idea. Thank you for sharing this.
Also dts can overlay, so we can add nodes, replace the value of properties, delete nodes(via directive /delete-node/), delete properties(via /delete-property/), the patches you used to patch dtb was very useful, but there is a better approach:
https://raw.githubusercontent.com/cattyhouse/pkgbuild-linux-phicomm-n1/master/meson-gxl-s905d-phicomm-n1.dts
reference : https://elinux.org/Device_Tree_Source_Undocumented