Merge patch series "RISC-V kasan rework"
authorPalmer Dabbelt <palmer@rivosinc.com>
Wed, 19 Apr 2023 14:24:56 +0000 (07:24 -0700)
committerPalmer Dabbelt <palmer@rivosinc.com>
Wed, 19 Apr 2023 14:24:56 +0000 (07:24 -0700)
Alexandre Ghiti <alexghiti@rivosinc.com> says:

As described in patch 2, our current kasan implementation is intricate,
so I tried to simplify the implementation and mimic what arm64/x86 are
doing.

In addition it fixes UEFI bootflow with a kasan kernel and kasan inline
instrumentation: all kasan configurations were tested on a large ubuntu
kernel with success with KASAN_KUNIT_TEST and KASAN_MODULE_TEST.

inline ubuntu config + uefi:
 sv39: OK
 sv48: OK
 sv57: OK

outline ubuntu config + uefi:
 sv39: OK
 sv48: OK
 sv57: OK

Actually 1 test always fails with KASAN_KUNIT_TEST that I have to check:
KASAN failure expected in "set_bit(nr, addr)", but none occurrred

Note that Palmer recently proposed to remove COMMAND_LINE_SIZE from the
userspace abi
https://lore.kernel.org/lkml/20221211061358.28035-1-palmer@rivosinc.com/T/
so that we can finally increase the command line to fit all kasan kernel
parameters.

All of this should hopefully fix the syzkaller riscv build that has been
failing for a few months now, any test is appreciated and if I can help
in any way, please ask.

* b4-shazam-merge:
  riscv: Unconditionnally select KASAN_VMALLOC if KASAN
  riscv: Fix ptdump when KASAN is enabled
  riscv: Fix EFI stub usage of KASAN instrumented strcmp function
  riscv: Move DTB_EARLY_BASE_VA to the kernel address space
  riscv: Rework kasan population functions
  riscv: Split early and final KASAN population functions

Link: https://lore.kernel.org/r/20230203075232.274282-1-alexghiti@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1  2 
arch/riscv/Kconfig
arch/riscv/mm/init.c

diff --combined arch/riscv/Kconfig
@@@ -12,13 -12,13 +12,13 @@@ config 32BI
  
  config RISCV
        def_bool y
 -      select ARCH_CLOCKSOURCE_INIT
        select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
        select ARCH_ENABLE_SPLIT_PMD_PTLOCK if PGTABLE_LEVELS > 2
 +      select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
        select ARCH_HAS_BINFMT_FLAT
        select ARCH_HAS_CURRENT_STACK_POINTER
 -      select ARCH_HAS_DEBUG_VM_PGTABLE
        select ARCH_HAS_DEBUG_VIRTUAL if MMU
 +      select ARCH_HAS_DEBUG_VM_PGTABLE
        select ARCH_HAS_DEBUG_WX
        select ARCH_HAS_FORTIFY_SOURCE
        select ARCH_HAS_GCOV_PROFILE_ALL
@@@ -33,7 -33,6 +33,7 @@@
        select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
        select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
        select ARCH_HAS_UBSAN_SANITIZE_ALL
 +      select ARCH_HAS_VDSO_DATA
        select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
        select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT
        select ARCH_STACKWALK
        select ARCH_USE_QUEUED_RWLOCKS
        select ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT if MMU
        select ARCH_WANT_FRAME_POINTERS
 -      select ARCH_WANT_GENERAL_HUGETLB
 +      select ARCH_WANT_GENERAL_HUGETLB if !RISCV_ISA_SVNAPOT
 +      select ARCH_WANT_HUGETLB_PAGE_OPTIMIZE_VMEMMAP
        select ARCH_WANT_HUGE_PMD_SHARE if 64BIT
 +      select ARCH_WANT_LD_ORPHAN_WARN if !XIP_KERNEL
        select ARCH_WANTS_THP_SWAP if HAVE_ARCH_TRANSPARENT_HUGEPAGE
        select BINFMT_FLAT_NO_DATA_START_OFFSET if !MMU
        select BUILDTIME_TABLE_SORT if MMU
 -      select CLONE_BACKWARDS
        select CLINT_TIMER if !MMU
 +      select CLONE_BACKWARDS
        select COMMON_CLK
        select CPU_PM if CPU_IDLE
        select EDAC_SUPPORT
@@@ -61,7 -58,6 +61,7 @@@
        select GENERIC_ATOMIC64 if !64BIT
        select GENERIC_CLOCKEVENTS_BROADCAST if SMP
        select GENERIC_EARLY_IOREMAP
 +      select GENERIC_ENTRY
        select GENERIC_GETTIMEOFDAY if HAVE_GENERIC_VDSO
        select GENERIC_IDLE_POLL_SETUP
        select GENERIC_IOREMAP if MMU
        select HAVE_ARCH_MMAP_RND_BITS if MMU
        select HAVE_ARCH_MMAP_RND_COMPAT_BITS if COMPAT
        select HAVE_ARCH_SECCOMP_FILTER
 +      select HAVE_ARCH_THREAD_STRUCT_WHITELIST
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_TRANSPARENT_HUGEPAGE if 64BIT && MMU
 -      select ARCH_ENABLE_THP_MIGRATION if TRANSPARENT_HUGEPAGE
 -      select HAVE_ARCH_THREAD_STRUCT_WHITELIST
        select HAVE_ARCH_VMAP_STACK if MMU && 64BIT
        select HAVE_ASM_MODVERSIONS
        select HAVE_CONTEXT_TRACKING_USER
        select HAVE_DEBUG_KMEMLEAK
        select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_EBPF_JIT if MMU
 +      select HAVE_FUNCTION_ARG_ACCESS_API
        select HAVE_FUNCTION_ERROR_INJECTION
        select HAVE_GCC_PLUGINS
        select HAVE_GENERIC_VDSO if MMU && 64BIT
        select HAVE_PERF_USER_STACK_DUMP
        select HAVE_POSIX_CPU_TIMERS_TASK_WORK
        select HAVE_REGS_AND_STACK_ACCESS_API
 -      select HAVE_FUNCTION_ARG_ACCESS_API
 +      select HAVE_RSEQ
        select HAVE_STACKPROTECTOR
        select HAVE_SYSCALL_TRACEPOINTS
 -      select HAVE_RSEQ
        select IRQ_DOMAIN
        select IRQ_FORCED_THREADING
+       select KASAN_VMALLOC if KASAN
        select MODULES_USE_ELF_RELA if MODULES
        select MODULE_SECTIONS if MODULES
        select OF
        select OF_IRQ
        select PCI_DOMAINS_GENERIC if PCI
        select PCI_MSI if PCI
 +      select RISCV_ALTERNATIVE if !XIP_KERNEL
        select RISCV_INTC
        select RISCV_TIMER if RISCV_SBI
        select SIFIVE_PLIC
        select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE
        select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL
        select HAVE_FUNCTION_GRAPH_TRACER
 -      select HAVE_FUNCTION_TRACER if !XIP_KERNEL
 +      select HAVE_FUNCTION_TRACER if !XIP_KERNEL && !PREEMPTION
  
  config ARCH_MMAP_RND_BITS_MIN
        default 18 if 64BIT
@@@ -180,8 -177,8 +181,8 @@@ config MM
  
  config PAGE_OFFSET
        hex
 -      default 0xC0000000 if 32BIT
 -      default 0x80000000 if 64BIT && !MMU
 +      default 0xC0000000 if 32BIT && MMU
 +      default 0x80000000 if !MMU
        default 0xff60000000000000 if 64BIT
  
  config KASAN_SHADOW_OFFSET
@@@ -239,16 -236,16 +240,16 @@@ config LOCKDEP_SUPPOR
  config RISCV_DMA_NONCOHERENT
        bool
        select ARCH_HAS_DMA_PREP_COHERENT
 -      select ARCH_HAS_SYNC_DMA_FOR_DEVICE
 -      select ARCH_HAS_SYNC_DMA_FOR_CPU
        select ARCH_HAS_SETUP_DMA_OPS
 +      select ARCH_HAS_SYNC_DMA_FOR_CPU
 +      select ARCH_HAS_SYNC_DMA_FOR_DEVICE
        select DMA_DIRECT_REMAP
  
  config AS_HAS_INSN
        def_bool $(as-instr,.insn r 51$(comma) 0$(comma) 0$(comma) t0$(comma) t0$(comma) zero)
  
  source "arch/riscv/Kconfig.socs"
 -source "arch/riscv/Kconfig.erratas"
 +source "arch/riscv/Kconfig.errata"
  
  menu "Platform type"
  
@@@ -282,6 -279,7 +283,6 @@@ config ARCH_RV32
        select GENERIC_LIB_ASHRDI3
        select GENERIC_LIB_LSHRDI3
        select GENERIC_LIB_UCMPDI2
 -      select MMU
  
  config ARCH_RV64I
        bool "RV64I"
@@@ -322,14 -320,6 +323,14 @@@ config SM
  
          If you don't know what to do here, say N.
  
 +config SCHED_MC
 +      bool "Multi-core scheduler support"
 +      depends on SMP
 +      help
 +        Multi-core scheduler support improves the CPU scheduler's decision
 +        making when dealing with multi-core CPU chips at a cost of slightly
 +        increased overhead in some places. If unsure say N here.
 +
  config NR_CPUS
        int "Maximum number of CPUs (2-512)"
        depends on SMP
@@@ -363,11 -353,11 +364,11 @@@ endchoic
  config NUMA
        bool "NUMA Memory Allocation and Scheduler Support"
        depends on SMP && MMU
 +      select ARCH_SUPPORTS_NUMA_BALANCING
        select GENERIC_ARCH_NUMA
 +      select NEED_PER_CPU_EMBED_FIRST_CHUNK
        select OF_NUMA
 -      select ARCH_SUPPORTS_NUMA_BALANCING
        select USE_PERCPU_NUMA_NODE_ID
 -      select NEED_PER_CPU_EMBED_FIRST_CHUNK
        help
          Enable NUMA (Non-Uniform Memory Access) support.
  
@@@ -388,9 -378,9 +389,9 @@@ config RISCV_ALTERNATIV
        depends on !XIP_KERNEL
        help
          This Kconfig allows the kernel to automatically patch the
 -        errata required by the execution platform at run time. The
 -        code patching is performed once in the boot stages. It means
 -        that the overhead from this mechanism is just taken once.
 +        erratum or cpufeature required by the execution platform at run
 +        time. The code patching overhead is minimal, as it's only done
 +        once at boot and once on each module load.
  
  config RISCV_ALTERNATIVE_EARLY
        bool
@@@ -408,32 -398,14 +409,32 @@@ config RISCV_ISA_
  
          If you don't know what to do here, say Y.
  
 +config RISCV_ISA_SVNAPOT
 +      bool "Svnapot extension support for supervisor mode NAPOT pages"
 +      depends on 64BIT && MMU
 +      depends on RISCV_ALTERNATIVE
 +      default y
 +      help
 +        Allow kernel to detect the Svnapot ISA-extension dynamically at boot
 +        time and enable its usage.
 +
 +        The Svnapot extension is used to mark contiguous PTEs as a range
 +        of contiguous virtual-to-physical translations for a naturally
 +        aligned power-of-2 (NAPOT) granularity larger than the base 4KB page
 +        size. When HUGETLBFS is also selected this option unconditionally
 +        allocates some memory for each NAPOT page size supported by the kernel.
 +        When optimizing for low memory consumption and for platforms without
 +        the Svnapot extension, it may be better to say N here.
 +
 +        If you don't know what to do here, say Y.
 +
  config RISCV_ISA_SVPBMT
 -      bool "SVPBMT extension support"
 +      bool "Svpbmt extension support for supervisor mode page-based memory types"
        depends on 64BIT && MMU
 -      depends on !XIP_KERNEL
 -      select RISCV_ALTERNATIVE
 +      depends on RISCV_ALTERNATIVE
        default y
        help
 -         Adds support to dynamically detect the presence of the SVPBMT
 +         Adds support to dynamically detect the presence of the Svpbmt
           ISA-extension (Supervisor-mode: page-based memory types) and
           enable its usage.
  
           that indicate the cacheability, idempotency, and ordering
           properties for access to that page.
  
 -         The SVPBMT extension is only available on 64Bit cpus.
 +         The Svpbmt extension is only available on 64-bit cpus.
  
           If you don't know what to do here, say Y.
  
 -config TOOLCHAIN_HAS_ZICBOM
 +config TOOLCHAIN_HAS_ZBB
        bool
        default y
 -      depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zicbom)
 -      depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zicbom)
 -      depends on LLD_VERSION >= 150000 || LD_VERSION >= 23800
 +      depends on !64BIT || $(cc-option,-mabi=lp64 -march=rv64ima_zbb)
 +      depends on !32BIT || $(cc-option,-mabi=ilp32 -march=rv32ima_zbb)
 +      depends on LLD_VERSION >= 150000 || LD_VERSION >= 23900
 +      depends on AS_IS_GNU
 +
 +config RISCV_ISA_ZBB
 +      bool "Zbb extension support for bit manipulation instructions"
 +      depends on TOOLCHAIN_HAS_ZBB
 +      depends on MMU
 +      depends on RISCV_ALTERNATIVE
 +      default y
 +      help
 +         Adds support to dynamically detect the presence of the ZBB
 +         extension (basic bit manipulation) and enable its usage.
 +
 +         The Zbb extension provides instructions to accelerate a number
 +         of bit-specific operations (count bit population, sign extending,
 +         bitrotation, etc).
 +
 +         If you don't know what to do here, say Y.
  
  config RISCV_ISA_ZICBOM
        bool "Zicbom extension support for non-coherent DMA operation"
 -      depends on TOOLCHAIN_HAS_ZICBOM
 -      depends on !XIP_KERNEL && MMU
 -      select RISCV_DMA_NONCOHERENT
 -      select RISCV_ALTERNATIVE
 +      depends on MMU
 +      depends on RISCV_ALTERNATIVE
        default y
 +      select RISCV_DMA_NONCOHERENT
        help
           Adds support to dynamically detect the presence of the ZICBOM
           extension (Cache Block Management Operations) and enable its
  
           If you don't know what to do here, say Y.
  
 +config RISCV_ISA_ZICBOZ
 +      bool "Zicboz extension support for faster zeroing of memory"
 +      depends on MMU
 +      depends on RISCV_ALTERNATIVE
 +      default y
 +      help
 +         Enable the use of the Zicboz extension (cbo.zero instruction)
 +         when available.
 +
 +         The Zicboz extension is used for faster zeroing of memory.
 +
 +         If you don't know what to do here, say Y.
 +
  config TOOLCHAIN_HAS_ZIHINTPAUSE
        bool
        default y
@@@ -549,9 -492,9 +550,9 @@@ config RISCV_BOOT_SPINWAI
  
  config KEXEC
        bool "Kexec system call"
 -      select KEXEC_CORE
 -      select HOTPLUG_CPU if SMP
        depends on MMU
 +      select HOTPLUG_CPU if SMP
 +      select KEXEC_CORE
        help
          kexec is a system call that implements the ability to shutdown your
          current kernel, and to start another kernel. It is like a reboot
  
  config KEXEC_FILE
        bool "kexec file based systmem call"
 +      depends on 64BIT && MMU
 +      select HAVE_IMA_KEXEC if IMA
        select KEXEC_CORE
        select KEXEC_ELF
 -      select HAVE_IMA_KEXEC if IMA
 -      depends on 64BIT && MMU
        help
          This is new version of kexec system call. This system call is
          file based and takes file descriptors as system call argument
@@@ -654,15 -597,15 +655,15 @@@ config EFI_STU
  config EFI
        bool "UEFI runtime support"
        depends on OF && !XIP_KERNEL
 -      select LIBFDT
 -      select UCS2_STRING
 -      select EFI_PARAMS_FROM_FDT
 -      select EFI_STUB
 +      depends on MMU
 +      default y
        select EFI_GENERIC_STUB
 +      select EFI_PARAMS_FROM_FDT
        select EFI_RUNTIME_WRAPPERS
 +      select EFI_STUB
 +      select LIBFDT
        select RISCV_ISA_C
 -      depends on MMU
 -      default y
 +      select UCS2_STRING
        help
          This option provides support for runtime services provided
          by UEFI firmware (such as non-volatile variables, realtime
@@@ -741,8 -684,8 +742,8 @@@ config PORTABL
        bool
        default !NONPORTABLE
        select EFI
 -      select OF
        select MMU
 +      select OF
  
  menu "Power management options"
  
diff --combined arch/riscv/mm/init.c
@@@ -57,7 -57,7 +57,7 @@@ unsigned long empty_zero_page[PAGE_SIZ
  EXPORT_SYMBOL(empty_zero_page);
  
  extern char _start[];
- #define DTB_EARLY_BASE_VA      PGDIR_SIZE
+ #define DTB_EARLY_BASE_VA      (ADDRESS_SPACE_END - (PTRS_PER_PGD / 2 * PGDIR_SIZE) + 1)
  void *_dtb_early_va __initdata;
  uintptr_t _dtb_early_pa __initdata;
  
@@@ -213,14 -213,6 +213,14 @@@ static void __init setup_bootmem(void
        phys_ram_end = memblock_end_of_DRAM();
        if (!IS_ENABLED(CONFIG_XIP_KERNEL))
                phys_ram_base = memblock_start_of_DRAM();
 +
 +      /*
 +       * In 64-bit, any use of __va/__pa before this point is wrong as we
 +       * did not know the start of DRAM before.
 +       */
 +      if (IS_ENABLED(CONFIG_64BIT))
 +              kernel_map.va_pa_offset = PAGE_OFFSET - phys_ram_base;
 +
        /*
         * memblock allocator is not aware of the fact that last 4K bytes of
         * the addressable memory can not be mapped because of IS_ERR_VALUE
  #ifdef CONFIG_MMU
  struct pt_alloc_ops pt_ops __initdata;
  
 -unsigned long riscv_pfn_base __ro_after_init;
 -EXPORT_SYMBOL(riscv_pfn_base);
 -
  pgd_t swapper_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
  pgd_t trampoline_pg_dir[PTRS_PER_PGD] __page_aligned_bss;
  static pte_t fixmap_pte[PTRS_PER_PTE] __page_aligned_bss;
@@@ -290,6 -285,7 +290,6 @@@ static pmd_t __maybe_unused early_dtb_p
  
  #ifdef CONFIG_XIP_KERNEL
  #define pt_ops                        (*(struct pt_alloc_ops *)XIP_FIXUP(&pt_ops))
 -#define riscv_pfn_base         (*(unsigned long  *)XIP_FIXUP(&riscv_pfn_base))
  #define trampoline_pg_dir      ((pgd_t *)XIP_FIXUP(trampoline_pg_dir))
  #define fixmap_pte             ((pte_t *)XIP_FIXUP(fixmap_pte))
  #define early_pg_dir           ((pgd_t *)XIP_FIXUP(early_pg_dir))
@@@ -675,16 -671,9 +675,16 @@@ void __init create_pgd_mapping(pgd_t *p
  
  static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
  {
 -      /* Upgrade to PMD_SIZE mappings whenever possible */
 -      base &= PMD_SIZE - 1;
 -      if (!base && size >= PMD_SIZE)
 +      if (!(base & (PGDIR_SIZE - 1)) && size >= PGDIR_SIZE)
 +              return PGDIR_SIZE;
 +
 +      if (!(base & (P4D_SIZE - 1)) && size >= P4D_SIZE)
 +              return P4D_SIZE;
 +
 +      if (!(base & (PUD_SIZE - 1)) && size >= PUD_SIZE)
 +              return PUD_SIZE;
 +
 +      if (!(base & (PMD_SIZE - 1)) && size >= PMD_SIZE)
                return PMD_SIZE;
  
        return PAGE_SIZE;
@@@ -993,22 -982,11 +993,22 @@@ asmlinkage void __init setup_vm(uintptr
        set_satp_mode();
  #endif
  
 -      kernel_map.va_pa_offset = PAGE_OFFSET - kernel_map.phys_addr;
 +      /*
 +       * In 64-bit, we defer the setup of va_pa_offset to setup_bootmem,
 +       * where we have the system memory layout: this allows us to align
 +       * the physical and virtual mappings and then make use of PUD/P4D/PGD
 +       * for the linear mapping. This is only possible because the kernel
 +       * mapping lies outside the linear mapping.
 +       * In 32-bit however, as the kernel resides in the linear mapping,
 +       * setup_vm_final can not change the mapping established here,
 +       * otherwise the same kernel addresses would get mapped to different
 +       * physical addresses (if the start of dram is different from the
 +       * kernel physical address start).
 +       */
 +      kernel_map.va_pa_offset = IS_ENABLED(CONFIG_64BIT) ?
 +                              0UL : PAGE_OFFSET - kernel_map.phys_addr;
        kernel_map.va_kernel_pa_offset = kernel_map.virt_addr - kernel_map.phys_addr;
  
 -      riscv_pfn_base = PFN_DOWN(kernel_map.phys_addr);
 -
        /*
         * The default maximal physical memory size is KERN_VIRT_SIZE for 32-bit
         * kernel, whereas for 64-bit kernel, the end of the virtual address
        pt_ops_set_fixmap();
  }
  
 -static void __init setup_vm_final(void)
 +static void __init create_linear_mapping_range(phys_addr_t start,
 +                                             phys_addr_t end)
  {
 +      phys_addr_t pa;
        uintptr_t va, map_size;
 -      phys_addr_t pa, start, end;
 +
 +      for (pa = start; pa < end; pa += map_size) {
 +              va = (uintptr_t)__va(pa);
 +              map_size = best_map_size(pa, end - pa);
 +
 +              create_pgd_mapping(swapper_pg_dir, va, pa, map_size,
 +                                 pgprot_from_va(va));
 +      }
 +}
 +
 +static void __init create_linear_mapping_page_table(void)
 +{
 +      phys_addr_t start, end;
        u64 i;
  
 -      /* Setup swapper PGD for fixmap */
 -      create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
 -                         __pa_symbol(fixmap_pgd_next),
 -                         PGDIR_SIZE, PAGE_TABLE);
 +#ifdef CONFIG_STRICT_KERNEL_RWX
 +      phys_addr_t ktext_start = __pa_symbol(_start);
 +      phys_addr_t ktext_size = __init_data_begin - _start;
 +      phys_addr_t krodata_start = __pa_symbol(__start_rodata);
 +      phys_addr_t krodata_size = _data - __start_rodata;
 +
 +      /* Isolate kernel text and rodata so they don't get mapped with a PUD */
 +      memblock_mark_nomap(ktext_start,  ktext_size);
 +      memblock_mark_nomap(krodata_start, krodata_size);
 +#endif
  
        /* Map all memory banks in the linear mapping */
        for_each_mem_range(i, &start, &end) {
                if (end >= __pa(PAGE_OFFSET) + memory_limit)
                        end = __pa(PAGE_OFFSET) + memory_limit;
  
 -              for (pa = start; pa < end; pa += map_size) {
 -                      va = (uintptr_t)__va(pa);
 -                      map_size = best_map_size(pa, end - pa);
 -
 -                      create_pgd_mapping(swapper_pg_dir, va, pa, map_size,
 -                                         pgprot_from_va(va));
 -              }
 +              create_linear_mapping_range(start, end);
        }
  
 +#ifdef CONFIG_STRICT_KERNEL_RWX
 +      create_linear_mapping_range(ktext_start, ktext_start + ktext_size);
 +      create_linear_mapping_range(krodata_start,
 +                                  krodata_start + krodata_size);
 +
 +      memblock_clear_nomap(ktext_start,  ktext_size);
 +      memblock_clear_nomap(krodata_start, krodata_size);
 +#endif
 +}
 +
 +static void __init setup_vm_final(void)
 +{
 +      /* Setup swapper PGD for fixmap */
 +      create_pgd_mapping(swapper_pg_dir, FIXADDR_START,
 +                         __pa_symbol(fixmap_pgd_next),
 +                         PGDIR_SIZE, PAGE_TABLE);
 +
 +      /* Map the linear mapping */
 +      create_linear_mapping_page_table();
 +
        /* Map the kernel */
        if (IS_ENABLED(CONFIG_64BIT))
                create_kernel_page_table(swapper_pg_dir, false);