riscv: libstub: Implement KASLR by using generic functions
authorAlexandre Ghiti <alexghiti@rivosinc.com>
Sat, 22 Jul 2023 12:38:50 +0000 (14:38 +0200)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 6 Sep 2023 02:49:31 +0000 (19:49 -0700)
We can now use arm64 functions to handle the move of the kernel physical
mapping: if KASLR is enabled, we will try to get a random seed from the
firmware, if not possible, the kernel will be moved to a location that
suits its alignment constraints.

Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Tested-by: Conor Dooley <conor.dooley@microchip.com>
Tested-by: Song Shuai <songshuaishuai@tinylab.org>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Sami Tolvanen <samitolvanen@google.com>
Link: https://lore.kernel.org/r/20230722123850.634544-6-alexghiti@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
arch/riscv/include/asm/efi.h
arch/riscv/kernel/image-vars.h
drivers/firmware/efi/libstub/Makefile
drivers/firmware/efi/libstub/riscv-stub.c

index 29e9a0d..00b24ba 100644 (file)
@@ -51,4 +51,6 @@ void efi_virtmap_unload(void);
 
 unsigned long stext_offset(void);
 
+void efi_icache_sync(unsigned long start, unsigned long end);
+
 #endif /* _ASM_EFI_H */
index 1561615..ea1a103 100644 (file)
@@ -27,6 +27,7 @@ __efistub__start              = _start;
 __efistub__start_kernel                = _start_kernel;
 __efistub__end                 = _end;
 __efistub__edata               = _edata;
+__efistub___init_text_end      = __init_text_end;
 __efistub_screen_info          = screen_info;
 
 #endif
index 11aba8a..dc90a31 100644 (file)
@@ -88,7 +88,7 @@ lib-$(CONFIG_EFI_GENERIC_STUB)        += efi-stub.o string.o intrinsics.o systable.o \
 lib-$(CONFIG_ARM)              += arm32-stub.o
 lib-$(CONFIG_ARM64)            += kaslr.o arm64.o arm64-stub.o smbios.o
 lib-$(CONFIG_X86)              += x86-stub.o
-lib-$(CONFIG_RISCV)            += riscv.o riscv-stub.o
+lib-$(CONFIG_RISCV)            += kaslr.o riscv.o riscv-stub.o
 lib-$(CONFIG_LOONGARCH)                += loongarch.o loongarch-stub.o
 
 CFLAGS_arm32-stub.o            := -DTEXT_OFFSET=$(TEXT_OFFSET)
index 145c9f0..c96d6dc 100644 (file)
@@ -30,32 +30,29 @@ efi_status_t handle_kernel_image(unsigned long *image_addr,
                                 efi_loaded_image_t *image,
                                 efi_handle_t image_handle)
 {
-       unsigned long kernel_size = 0;
-       unsigned long preferred_addr;
+       unsigned long kernel_size, kernel_codesize, kernel_memsize;
        efi_status_t status;
 
        kernel_size = _edata - _start;
+       kernel_codesize = __init_text_end - _start;
+       kernel_memsize = kernel_size + (_end - _edata);
        *image_addr = (unsigned long)_start;
-       *image_size = kernel_size + (_end - _edata);
-
-       /*
-        * RISC-V kernel maps PAGE_OFFSET virtual address to the same physical
-        * address where kernel is booted. That's why kernel should boot from
-        * as low as possible to avoid wastage of memory. Currently, dram_base
-        * is occupied by the firmware. So the preferred address for kernel to
-        * boot is next aligned address. If preferred address is not available,
-        * relocate_kernel will fall back to efi_low_alloc_above to allocate
-        * lowest possible memory region as long as the address and size meets
-        * the alignment constraints.
-        */
-       preferred_addr = EFI_KIMG_PREFERRED_ADDRESS;
-       status = efi_relocate_kernel(image_addr, kernel_size, *image_size,
-                                    preferred_addr, efi_get_kimg_min_align(),
-                                    0x0);
+       *image_size = kernel_memsize;
+       *reserve_size = *image_size;
 
+       status = efi_kaslr_relocate_kernel(image_addr,
+                                          reserve_addr, reserve_size,
+                                          kernel_size, kernel_codesize, kernel_memsize,
+                                          efi_kaslr_get_phys_seed(image_handle));
        if (status != EFI_SUCCESS) {
                efi_err("Failed to relocate kernel\n");
                *image_size = 0;
        }
+
        return status;
 }
+
+void efi_icache_sync(unsigned long start, unsigned long end)
+{
+       asm volatile ("fence.i" ::: "memory");
+}