2021-04-01 18:03:13

by Jinyang He

[permalink] [raw]
Subject: [PATCH RFC 0/3] Some update for relocate

Two questions at least here,

1. cavium-octeon platform seems start with smp cpus, it may broke this function
2. Commit 15ad838d281b ("[MIPS] Always do the ARC64_TWIDDLE_PC thing."), I don't
know whether broken it.

So RFC to get helps. Thanks!

And Patch3 can be tested by vmlinuz. e.g. Use the follow patch,

diff --git a/arch/mips/boot/compressed/Makefile b/arch/mips/boot/compressed/Makefile
index f93f72b..499b38d 100644
--- a/arch/mips/boot/compressed/Makefile
+++ b/arch/mips/boot/compressed/Makefile
@@ -28,12 +28,11 @@ KBUILD_CFLAGS := $(filter-out -march=loongson3a, $(KBUILD_CFLAGS)) -march=mips64
endif

KBUILD_CFLAGS := $(KBUILD_CFLAGS) -D__KERNEL__ -D__DISABLE_EXPORTS \
- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull"
-
-KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__ASSEMBLY__ \
- -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) \
+ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE) -D"VMLINUX_LOAD_ADDRESS_ULL=$(VMLINUX_LOAD_ADDRESS)ull" \
-DKERNEL_ENTRY=$(VMLINUX_ENTRY_ADDRESS)

+KBUILD_AFLAGS := $(KBUILD_AFLAGS) -D__ASSEMBLY__ -DBOOT_HEAP_SIZE=$(BOOT_HEAP_SIZE)
+
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
GCOV_PROFILE := n
diff --git a/arch/mips/boot/compressed/decompress.c b/arch/mips/boot/compressed/decompress.c
index 3d70d15..3f5cac9 100644
--- a/arch/mips/boot/compressed/decompress.c
+++ b/arch/mips/boot/compressed/decompress.c
@@ -85,9 +85,11 @@ void __stack_chk_fail(void)
error("stack-protector: Kernel stack is corrupted\n");
}

-void decompress_kernel(unsigned long boot_heap_start)
+unsigned long decompress_kernel(unsigned long boot_heap_start)
{
unsigned long zimage_start, zimage_size;
+ unsigned long offset = 0x8000000;
+ unsigned long long load_address = VMLINUX_LOAD_ADDRESS_ULL + offset;

zimage_start = (unsigned long)(&__image_begin);
zimage_size = (unsigned long)(&__image_end) -
@@ -105,12 +107,12 @@ void decompress_kernel(unsigned long boot_heap_start)

/* Display standard Linux/MIPS boot prompt */
puts("Uncompressing Linux at load address ");
- puthex(VMLINUX_LOAD_ADDRESS_ULL);
+ puthex(load_address);
puts("\n");

/* Decompress the kernel with according algorithm */
__decompress((char *)zimage_start, zimage_size, 0, 0,
- (void *)VMLINUX_LOAD_ADDRESS_ULL, 0, 0, error);
+ (void *)load_address, 0, 0, error);

if (IS_ENABLED(CONFIG_MIPS_RAW_APPENDED_DTB) &&
fdt_magic((void *)&__appended_dtb) == FDT_MAGIC) {
@@ -125,14 +127,16 @@ void decompress_kernel(unsigned long boot_heap_start)
image_size = ALIGN(image_size, STRUCT_ALIGNMENT);

puts("Copy device tree to address ");
- puthex(VMLINUX_LOAD_ADDRESS_ULL + image_size);
+ puthex(load_address + image_size);
puts("\n");

/* copy dtb to where the booted kernel will expect it */
- memcpy((void *)VMLINUX_LOAD_ADDRESS_ULL + image_size,
+ memcpy((void *)load_address + image_size,
__appended_dtb, dtb_size);
}

/* FIXME: should we flush cache here? */
puts("Now, booting the kernel...\n");
+
+ return (KERNEL_ENTRY + offset);
}
diff --git a/arch/mips/boot/compressed/head.S b/arch/mips/boot/compressed/head.S
index 5795d0a..36c5809 100644
--- a/arch/mips/boot/compressed/head.S
+++ b/arch/mips/boot/compressed/head.S
@@ -40,8 +40,7 @@
move a1, s1
move a2, s2
move a3, s3
- PTR_LI t9, KERNEL_ENTRY
- jalr t9
+ jalr v0

3:
b 3b

Jinyang He (3):
MIPS: relocate: Only compile relocs when CONFIG_RELOCATABLE is enabled
MIPS: relocate: Use CONFIG_RANDOMIZE_BASE to configure kaslr
MIPS: relocate: Add support to relocate kernel auto

arch/mips/Makefile | 2 +
arch/mips/cavium-octeon/smp.c | 8 +-
arch/mips/generic/init.c | 4 +-
arch/mips/include/asm/bootinfo.h | 4 +-
.../asm/mach-cavium-octeon/kernel-entry-init.h | 4 +-
arch/mips/kernel/Makefile | 2 +-
arch/mips/kernel/head.S | 155 ++++++++++++++++++++-
arch/mips/kernel/{relocate.c => kaslr.c} | 15 --
8 files changed, 165 insertions(+), 29 deletions(-)
rename arch/mips/kernel/{relocate.c => kaslr.c} (97%)

--
2.1.0


2021-04-01 18:03:24

by Jinyang He

[permalink] [raw]
Subject: [PATCH RFC 1/3] MIPS: relocate: Only compile relocs when CONFIG_RELOCATABLE is enabled

Relocs is used for create relocate information, only CONFIG_RELOCATABLE
is enabled can it be used.

Signed-off-by: Jinyang He <[email protected]>
---
arch/mips/Makefile | 2 ++
1 file changed, 2 insertions(+)

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index e71d587..cb54d86 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -17,7 +17,9 @@ archscripts: scripts_basic
ifeq ($(CONFIG_CPU_LOONGSON3_WORKAROUNDS),y)
$(Q)$(MAKE) $(build)=arch/mips/tools loongson3-llsc-check
endif
+ifeq ($(CONFIG_RELOCATABLE),y)
$(Q)$(MAKE) $(build)=arch/mips/boot/tools relocs
+endif

KBUILD_DEFCONFIG := 32r2el_defconfig
KBUILD_DTBS := dtbs
--
2.1.0

2021-04-01 18:03:56

by Jinyang He

[permalink] [raw]
Subject: [PATCH RFC 3/3] MIPS: relocate: Add support to relocate kernel auto

These asm code is based on relocate.c. And in this stage,
only do relocate for _text and ex_table.

Signed-off-by: Jinyang He <[email protected]>
---
arch/mips/kernel/head.S | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 149 insertions(+)

diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index a25af1d..dc59b11 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -13,6 +13,7 @@
* Kevin Kissell, [email protected] and Carsten Langgaard, [email protected]
* Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
*/
+
#include <linux/init.h>
#include <linux/threads.h>

@@ -26,6 +27,152 @@

#include <kernel-entry-init.h>

+ .macro do_relocate_kernel
+ .set push
+#ifdef CONFIG_RELOCATABLE
+#define R_MIPS_32 2
+#define R_MIPS_26 4
+#define R_MIPS_HI16 5
+#define R_MIPS_64 18
+ /* Save args */
+ move s0, a0
+ move s1, a1
+ move s2, a2
+ move s3, a3
+
+ /* Whether the PC meets expectation */
+ bal 1f
+1: move a0, ra
+ PTR_LA a1, 1b
+ PTR_SUB a0, a0, a1
+ beqz a0, 999f
+
+ /* Whether offset 64KB aligned */
+ and t0, a0, 0xffff
+ bnez t0, 999f
+
+ /* Whether current _text and _end are in the PC region */
+ PTR_LA t0, _end
+ PTR_ADDU t1, t0, a0
+ PTR_SRL t1, 28
+ PTR_SRL t0, 28
+ bne t0, t1, 999f
+
+ PTR_LA t0, _text
+ PTR_ADDU t1, t0, a0
+ move a3, t1
+ PTR_SRL t1, 28
+ PTR_SRL t0, 28
+ bne t0, t1, 999f
+
+ /* get current __start/stop___ex_table address */
+ PTR_LA a1, __start___ex_table
+ PTR_ADDU a1, a0
+ PTR_LA a2, __stop___ex_table
+ PTR_ADDU a2, a0
+
+ /*
+ * a0: offset
+ * a1: current __start___ex_table
+ * a2: current __stop___ex_table
+ */
+1: beq a1, a2, 998f
+ PTR_L t0, 0(a1)
+ PTR_ADDU t0, a0
+ PTR_S t0, 0(a1)
+ LONG_ADDIU a1, PTRSIZE
+ b 1b
+
+998:
+ /* get current _relocation_start address */
+ PTR_LA a1, _relocation_start
+ PTR_ADDU a1, a0
+
+ /*
+ * a0: offset
+ * a1: _relocation_start[]
+ * a2: offset >> 16, to relocate R_MIPS_HI16
+ * a3: current _text
+ * t0: to load _relocation_start[]
+ * t1: relocation type
+ * t2: current relocate position
+ * t3: temporarily
+ * t8: 0x00ffffff, mask, to get relocate position
+ * t9: offset >> 2, to relocate R_MIPS_26
+ */
+ li t8, 0x00ffffff
+ LONG_SRL t9, a0, 2
+ LONG_SRL a2, a0, 16
+1: lw t0, 0(a1)
+ beqz t0, 900f
+ LONG_SRL t1, t0, 24
+ and t1, 0xff
+ and t2, t0, t8
+ LONG_SLL t2, 2
+ PTR_ADDU t2, a3
+
+ li t3, R_MIPS_64
+ beq t1, t3, 964f
+ li t3, R_MIPS_32
+ beq t1, t3, 932f
+ li t3, R_MIPS_26
+ beq t1, t3, 926f
+ li t3, R_MIPS_HI16
+ beq t1, t3, 916f
+ b 999f
+
+964:
+#ifdef CONFIG_64BIT
+ ld t3, 0(t2)
+ LONG_ADDU t3, a0
+ sd t3, 0(t2)
+#endif
+ LONG_ADDIU a1, 4
+ b 1b
+
+932:
+ lw t3, 0(t2)
+ LONG_ADDU t3, a0
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+926:
+ lw t3, 0(t2)
+ LONG_ADDU t3, t9
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+916:
+ lw t3, 0(t2)
+ LONG_ADDU t3, a2
+ sw t3, 0(t2)
+ LONG_ADDIU a1, 4
+ b 1b
+
+900:
+ /* Complete! And flush i-cache */
+ PTR_LA a0, _text
+ PTR_LA a1, _end
+ synci 0(a0)
+ rdhwr t0, $1
+ beqz t0, 999f
+ PTR_ADDU a0, t0
+ PTR_SUBU t0, a1, a0
+ bgtz t0, 900b
+ sync
+
+999:
+ /* Restore args */
+ move a0, s0
+ move a1, s1
+ move a2, s2
+ move a3, s3
+#endif /* CONFIG_RELOCATABLE */
+ .set pop
+ .endm
+
/*
* For the moment disable interrupts, mark the kernel mode and
* set ST0_KX so that the CPU does not spit fire when using
@@ -83,6 +230,8 @@ FEXPORT(__kernel_entry)

NESTED(kernel_entry, 16, sp) # kernel entry point

+ do_relocate_kernel
+
kernel_entry_setup # cpu specific setup

setup_c0_status_pri
--
2.1.0

2021-04-01 18:04:03

by Jinyang He

[permalink] [raw]
Subject: [PATCH RFC 2/3] MIPS: relocate: Use CONFIG_RANDOMIZE_BASE to configure kaslr

Currently, the difference between using CONFIG_RELOCATABLE and
CONFIG_RANDOMIZE_BASE is determine_relocation_address().
CONFIG_RANDOMIZE_BASE achieves randomization, but CONFIG_RELOCATABLE
relocate the kernel is very limited, currently returns a constant.
Therefore, abandoned determine_relocation_address() on CONFIG_RELOCATABLE.
Rename relocate.c to kaslr.c and use CONFIG_RANDOMIZE_BASE to configure
the kaslr function.

Signed-off-by: Jinyang He <[email protected]>
---
arch/mips/cavium-octeon/smp.c | 8 ++++----
arch/mips/generic/init.c | 4 ++--
arch/mips/include/asm/bootinfo.h | 4 ++--
.../include/asm/mach-cavium-octeon/kernel-entry-init.h | 4 ++--
arch/mips/kernel/Makefile | 2 +-
arch/mips/kernel/head.S | 6 +++---
arch/mips/kernel/{relocate.c => kaslr.c} | 15 ---------------
7 files changed, 14 insertions(+), 29 deletions(-)
rename arch/mips/kernel/{relocate.c => kaslr.c} (97%)

diff --git a/arch/mips/cavium-octeon/smp.c b/arch/mips/cavium-octeon/smp.c
index 66ce552..dfdbc79 100644
--- a/arch/mips/cavium-octeon/smp.c
+++ b/arch/mips/cavium-octeon/smp.c
@@ -28,9 +28,9 @@
volatile unsigned long octeon_processor_boot = 0xff;
volatile unsigned long octeon_processor_sp;
volatile unsigned long octeon_processor_gp;
-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE
volatile unsigned long octeon_processor_relocated_kernel_entry;
-#endif /* CONFIG_RELOCATABLE */
+#endif /* CONFIG_RANDOMIZE_BASE */

#ifdef CONFIG_HOTPLUG_CPU
uint64_t octeon_bootloader_entry_addr;
@@ -190,7 +190,7 @@ static void __init octeon_smp_setup(void)
}


-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE
int plat_post_relocation(long offset)
{
unsigned long entry = (unsigned long)kernel_entry;
@@ -200,7 +200,7 @@ int plat_post_relocation(long offset)

return 0;
}
-#endif /* CONFIG_RELOCATABLE */
+#endif /* CONFIG_RANDOMIZE_BASE */

/**
* Firmware CPU startup hook
diff --git a/arch/mips/generic/init.c b/arch/mips/generic/init.c
index 1842cdd..f7a4e29 100644
--- a/arch/mips/generic/init.c
+++ b/arch/mips/generic/init.c
@@ -82,7 +82,7 @@ void __init *plat_get_fdt(void)
return (void *)fdt;
}

-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE

void __init plat_fdt_relocated(void *new_location)
{
@@ -97,7 +97,7 @@ void __init plat_fdt_relocated(void *new_location)
fw_arg1 = (unsigned long)new_location;
}

-#endif /* CONFIG_RELOCATABLE */
+#endif /* CONFIG_RANDOMIZE_BASE */

void __init plat_mem_setup(void)
{
diff --git a/arch/mips/include/asm/bootinfo.h b/arch/mips/include/asm/bootinfo.h
index 5be10ece..6b37663 100644
--- a/arch/mips/include/asm/bootinfo.h
+++ b/arch/mips/include/asm/bootinfo.h
@@ -169,7 +169,7 @@ static inline void plat_swiotlb_setup(void) {}
*/
extern void *plat_get_fdt(void);

-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE

/**
* plat_fdt_relocated() - Update platform's information about relocated dtb
@@ -180,7 +180,7 @@ extern void *plat_get_fdt(void);
*/
void plat_fdt_relocated(void *new_location);

-#endif /* CONFIG_RELOCATABLE */
+#endif /* CONFIG_RANDOMIZE_BASE */
#endif /* CONFIG_USE_OF */

#endif /* _ASM_BOOTINFO_H */
diff --git a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
index c38b38c..e66767d 100644
--- a/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
+++ b/arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
@@ -100,7 +100,7 @@
#

octeon_spin_wait_boot:
-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE
PTR_LA t0, octeon_processor_relocated_kernel_entry
LONG_L t0, (t0)
beq zero, t0, 1f
@@ -109,7 +109,7 @@
jr t0
nop
1:
-#endif /* CONFIG_RELOCATABLE */
+#endif /* CONFIG_RANDOMIZE_BASE */

# This is the variable where the next core to boot is stored
PTR_LA t0, octeon_processor_boot
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index b4a57f1..bf7ac86 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -92,7 +92,7 @@ obj-$(CONFIG_I8253) += i8253.o

obj-$(CONFIG_GPIO_TXX9) += gpio_txx9.o

-obj-$(CONFIG_RELOCATABLE) += relocate.o
+obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o

obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o crash.o
obj-$(CONFIG_CRASH_DUMP) += crash_dump.o
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index b825ed4..a25af1d 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -118,7 +118,7 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
set_saved_sp sp, t0, t1
PTR_SUBU sp, 4 * SZREG # init stack pointer

-#ifdef CONFIG_RELOCATABLE
+#ifdef CONFIG_RANDOMIZE_BASE
/* Copy kernel and apply the relocations */
jal relocate_kernel

@@ -136,9 +136,9 @@ NESTED(kernel_entry, 16, sp) # kernel entry point
* newly sync'd icache.
*/
jr.hb v0
-#else /* !CONFIG_RELOCATABLE */
+#else /* !CONFIG_RANDOMIZE_BASE */
j start_kernel
-#endif /* !CONFIG_RELOCATABLE */
+#endif /* !CONFIG_RANDOMIZE_BASE */
END(kernel_entry)

#ifdef CONFIG_SMP
diff --git a/arch/mips/kernel/relocate.c b/arch/mips/kernel/kaslr.c
similarity index 97%
rename from arch/mips/kernel/relocate.c
rename to arch/mips/kernel/kaslr.c
index 499a535..6742d58 100644
--- a/arch/mips/kernel/relocate.c
+++ b/arch/mips/kernel/kaslr.c
@@ -188,8 +188,6 @@ static int __init relocate_exception_table(long offset)
return 0;
}

-#ifdef CONFIG_RANDOMIZE_BASE
-
static inline __init unsigned long rotate_xor(unsigned long hash,
const void *area, size_t size)
{
@@ -280,19 +278,6 @@ static inline void __init *determine_relocation_address(void)
return RELOCATED(dest);
}

-#else
-
-static inline void __init *determine_relocation_address(void)
-{
- /*
- * Choose a new address for the kernel
- * For now we'll hard code the destination
- */
- return (void *)0xffffffff81000000;
-}
-
-#endif
-
static inline int __init relocation_addr_valid(void *loc_new)
{
if ((unsigned long)loc_new & 0x0000ffff) {
--
2.1.0