Merge tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Sep 2021 18:58:20 +0000 (11:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 10 Sep 2021 18:58:20 +0000 (11:58 -0700)
Pull arm64 fixes from Catalin Marinas:

 - Limit the linear region to 51-bit when KVM is running in nVHE mode.

   Otherwise, depending on the placement of the ID map, kernel-VA to
   hyp-VA translations may produce addresses that either conflict with
   other HYP mappings or generate addresses outside of the 52-bit
   addressable range.

 - Instruct kmemleak not to scan the memory reserved for kdump as this
   range is removed from the kernel linear map and therefore not
   accessible.

* tag 'arm64-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux:
  arm64: kdump: Skip kmemleak scan reserved memory for kdump
  arm64: mm: limit linear region to 51 bits for KVM in nVHE mode

1  2 
arch/arm64/mm/init.c

@@@ -220,10 -254,59 +226,24 @@@ static int __init early_mem(char *p
  }
  early_param("mem", early_mem);
  
 -static int __init early_init_dt_scan_usablemem(unsigned long node,
 -              const char *uname, int depth, void *data)
 -{
 -      struct memblock_region *usablemem = data;
 -      const __be32 *reg;
 -      int len;
 -
 -      if (depth != 1 || strcmp(uname, "chosen") != 0)
 -              return 0;
 -
 -      reg = of_get_flat_dt_prop(node, "linux,usable-memory-range", &len);
 -      if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells)))
 -              return 1;
 -
 -      usablemem->base = dt_mem_next_cell(dt_root_addr_cells, &reg);
 -      usablemem->size = dt_mem_next_cell(dt_root_size_cells, &reg);
 -
 -      return 1;
 -}
 -
 -static void __init fdt_enforce_memory_region(void)
 -{
 -      struct memblock_region reg = {
 -              .size = 0,
 -      };
 -
 -      of_scan_flat_dt(early_init_dt_scan_usablemem, &reg);
 -
 -      if (reg.size)
 -              memblock_cap_memory_range(reg.base, reg.size);
 -}
 -
  void __init arm64_memblock_init(void)
  {
-       const s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual);
+       s64 linear_region_size = PAGE_END - _PAGE_OFFSET(vabits_actual);
+       /*
+        * Corner case: 52-bit VA capable systems running KVM in nVHE mode may
+        * be limited in their ability to support a linear map that exceeds 51
+        * bits of VA space, depending on the placement of the ID map. Given
+        * that the placement of the ID map may be randomized, let's simply
+        * limit the kernel's linear map to 51 bits as well if we detect this
+        * configuration.
+        */
+       if (IS_ENABLED(CONFIG_KVM) && vabits_actual == 52 &&
+           is_hyp_mode_available() && !is_kernel_in_hyp_mode()) {
+               pr_info("Capping linear region to 51 bits for KVM in nVHE mode on LVA capable hardware.\n");
+               linear_region_size = min_t(u64, linear_region_size, BIT(51));
+       }
  
 -      /* Handle linux,usable-memory-range property */
 -      fdt_enforce_memory_region();
 -
        /* Remove memory above our supported physical address size */
        memblock_remove(1ULL << PHYS_MASK_SHIFT, ULLONG_MAX);