]> Git Repo - linux.git/commitdiff
Merge tag 'libnvdimm-fixes-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <[email protected]>
Sun, 29 Sep 2019 17:33:41 +0000 (10:33 -0700)
committerLinus Torvalds <[email protected]>
Sun, 29 Sep 2019 17:33:41 +0000 (10:33 -0700)
More libnvdimm updates from Dan Williams:

 - Complete the reworks to interoperate with powerpc dynamic huge page
   sizes

 - Fix a crash due to missed accounting for the powerpc 'struct
   page'-memmap mapping granularity

 - Fix badblock initialization for volatile (DRAM emulated) pmem ranges

 - Stop triggering request_key() notifications to userspace when
   NVDIMM-security is disabled / not present

 - Miscellaneous small fixups

* tag 'libnvdimm-fixes-5.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm:
  libnvdimm/region: Enable MAP_SYNC for volatile regions
  libnvdimm: prevent nvdimm from requesting key when security is disabled
  libnvdimm/region: Initialize bad block for volatile namespaces
  libnvdimm/nfit_test: Fix acpi_handle redefinition
  libnvdimm/altmap: Track namespace boundaries in altmap
  libnvdimm: Fix endian conversion issues 
  libnvdimm/dax: Pick the right alignment default when creating dax devices
  powerpc/book3s64: Export has_transparent_hugepage() related functions.

1  2 
arch/powerpc/include/asm/book3s/64/radix.h
arch/powerpc/mm/book3s64/radix_pgtable.c
drivers/nvdimm/pfn_devs.c
include/linux/huge_mm.h
include/linux/memremap.h

index 574eca33f8930d4d52bc2c9cebfd8ed696ee0a20,65a6966f1de49e0358da933f83ac50c2eadb815f..d97db3ad9aae210972a564178fb7be116d0cb21a
@@@ -254,7 -254,13 +254,13 @@@ extern void radix__pgtable_trans_huge_d
  extern pgtable_t radix__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
  extern pmd_t radix__pmdp_huge_get_and_clear(struct mm_struct *mm,
                                      unsigned long addr, pmd_t *pmdp);
- extern int radix__has_transparent_hugepage(void);
+ static inline int radix__has_transparent_hugepage(void)
+ {
+       /* For radix 2M at PMD level means thp */
+       if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
+               return 1;
+       return 0;
+ }
  #endif
  
  extern int __meminit radix__vmemmap_create_mapping(unsigned long start,
@@@ -266,6 -272,9 +272,6 @@@ extern void radix__vmemmap_remove_mappi
  extern int radix__map_kernel_page(unsigned long ea, unsigned long pa,
                                 pgprot_t flags, unsigned int psz);
  
 -extern int radix__ioremap_range(unsigned long ea, phys_addr_t pa,
 -                              unsigned long size, pgprot_t prot, int nid);
 -
  static inline unsigned long radix__get_tree_size(void)
  {
        unsigned long rts_field;
index 3a1fbf9cb8f86efbb95b94443b55ca6ed2fc1405,dc7a38f0a45ba0a0f87e3c2f01e1e68662b79952..6ee17d09649c3764e518fc8c58a0bcf659a89893
  #include <asm/sections.h>
  #include <asm/trace.h>
  #include <asm/uaccess.h>
 +#include <asm/ultravisor.h>
  
  #include <trace/events/thp.h>
  
  unsigned int mmu_pid_bits;
  unsigned int mmu_base_pid;
  
 -static int native_register_process_table(unsigned long base, unsigned long pg_sz,
 -                                       unsigned long table_size)
 -{
 -      unsigned long patb0, patb1;
 -
 -      patb0 = be64_to_cpu(partition_tb[0].patb0);
 -      patb1 = base | table_size | PATB_GR;
 -
 -      mmu_partition_table_set_entry(0, patb0, patb1);
 -
 -      return 0;
 -}
 -
  static __ref void *early_alloc_pgtable(unsigned long size, int nid,
                        unsigned long region_start, unsigned long region_end)
  {
@@@ -368,6 -380,18 +368,6 @@@ static void __init radix_init_pgtable(v
         */
        rts_field = radix__get_tree_size();
        process_tb->prtb0 = cpu_to_be64(rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE);
 -      /*
 -       * Fill in the partition table. We are suppose to use effective address
 -       * of process table here. But our linear mapping also enable us to use
 -       * physical address here.
 -       */
 -      register_process_table(__pa(process_tb), 0, PRTB_SIZE_SHIFT - 12);
 -      pr_info("Process table %p and radix root for kernel: %p\n", process_tb, init_mm.pgd);
 -      asm volatile("ptesync" : : : "memory");
 -      asm volatile(PPC_TLBIE_5(%0,%1,2,1,1) : :
 -                   "r" (TLBIEL_INVAL_SET_LPID), "r" (0));
 -      asm volatile("eieio; tlbsync; ptesync" : : : "memory");
 -      trace_tlbie(0, 0, TLBIEL_INVAL_SET_LPID, 0, 2, 1, 1);
  
        /*
         * The init_mm context is given the first available (non-zero) PID,
  
  static void __init radix_init_partition_table(void)
  {
 -      unsigned long rts_field, dw0;
 +      unsigned long rts_field, dw0, dw1;
  
        mmu_partition_table_init();
        rts_field = radix__get_tree_size();
        dw0 = rts_field | __pa(init_mm.pgd) | RADIX_PGD_INDEX_SIZE | PATB_HR;
 -      mmu_partition_table_set_entry(0, dw0, 0);
 +      dw1 = __pa(process_tb) | (PRTB_SIZE_SHIFT - 12) | PATB_GR;
 +      mmu_partition_table_set_entry(0, dw0, dw1, false);
  
        pr_info("Initializing Radix MMU\n");
 -      pr_info("Partition table %p\n", partition_tb);
 -}
 -
 -void __init radix_init_native(void)
 -{
 -      register_process_table = native_register_process_table;
  }
  
  static int __init get_idx_from_shift(unsigned int shift)
@@@ -592,9 -621,8 +592,9 @@@ void __init radix__early_init_mmu(void
        __pmd_frag_nr = RADIX_PMD_FRAG_NR;
        __pmd_frag_size_shift = RADIX_PMD_FRAG_SIZE_SHIFT;
  
 +      radix_init_pgtable();
 +
        if (!firmware_has_feature(FW_FEATURE_LPAR)) {
 -              radix_init_native();
                lpcr = mfspr(SPRN_LPCR);
                mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
                radix_init_partition_table();
  
        memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE);
  
 -      radix_init_pgtable();
        /* Switch to the guard PID before turning on MMU */
        radix__switch_mmu_context(NULL, &init_mm);
 -      if (cpu_has_feature(CPU_FTR_HVMODE))
 -              tlbiel_all();
 +      tlbiel_all();
  }
  
  void radix__early_init_mmu_secondary(void)
                lpcr = mfspr(SPRN_LPCR);
                mtspr(SPRN_LPCR, lpcr | LPCR_UPRT | LPCR_HR);
  
 -              mtspr(SPRN_PTCR,
 -                    __pa(partition_tb) | (PATB_SIZE_SHIFT - 12));
 +              set_ptcr_when_no_uv(__pa(partition_tb) |
 +                                  (PATB_SIZE_SHIFT - 12));
 +
                radix_init_amor();
        }
  
        radix__switch_mmu_context(NULL, &init_mm);
 -      if (cpu_has_feature(CPU_FTR_HVMODE))
 -              tlbiel_all();
 +      tlbiel_all();
  }
  
  void radix__mmu_cleanup_all(void)
        if (!firmware_has_feature(FW_FEATURE_LPAR)) {
                lpcr = mfspr(SPRN_LPCR);
                mtspr(SPRN_LPCR, lpcr & ~LPCR_UPRT);
 -              mtspr(SPRN_PTCR, 0);
 +              set_ptcr_when_no_uv(0);
                powernv_set_nmmu_ptcr(0);
                radix__flush_tlb_all();
        }
@@@ -707,8 -737,8 +707,8 @@@ static int __meminit stop_machine_chang
  
        spin_unlock(&init_mm.page_table_lock);
        pte_clear(&init_mm, params->aligned_start, params->pte);
 -      create_physical_mapping(params->aligned_start, params->start, -1);
 -      create_physical_mapping(params->end, params->aligned_end, -1);
 +      create_physical_mapping(__pa(params->aligned_start), __pa(params->start), -1);
 +      create_physical_mapping(__pa(params->end), __pa(params->aligned_end), -1);
        spin_lock(&init_mm.page_table_lock);
        return 0;
  }
@@@ -872,7 -902,7 +872,7 @@@ int __meminit radix__create_section_map
                return -1;
        }
  
 -      return create_physical_mapping(start, end, nid);
 +      return create_physical_mapping(__pa(start), __pa(end), nid);
  }
  
  int __meminit radix__remove_section_mapping(unsigned long start, unsigned long end)
@@@ -1027,13 -1057,6 +1027,6 @@@ pmd_t radix__pmdp_huge_get_and_clear(st
        return old_pmd;
  }
  
- int radix__has_transparent_hugepage(void)
- {
-       /* For radix 2M at PMD level means thp */
-       if (mmu_psize_defs[MMU_PAGE_2M].shift == PMD_SHIFT)
-               return 1;
-       return 0;
- }
  #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
  
  void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep,
@@@ -1188,6 -1211,26 +1181,6 @@@ int pmd_free_pte_page(pmd_t *pmd, unsig
        return 1;
  }
  
 -int radix__ioremap_range(unsigned long ea, phys_addr_t pa, unsigned long size,
 -                      pgprot_t prot, int nid)
 -{
 -      if (likely(slab_is_available())) {
 -              int err = ioremap_page_range(ea, ea + size, pa, prot);
 -              if (err)
 -                      unmap_kernel_range(ea, size);
 -              return err;
 -      } else {
 -              unsigned long i;
 -
 -              for (i = 0; i < size; i += PAGE_SIZE) {
 -                      int err = map_kernel_page(ea + i, pa + i, prot);
 -                      if (WARN_ON_ONCE(err)) /* Should clean up */
 -                              return err;
 -              }
 -              return 0;
 -      }
 -}
 -
  int __init arch_ioremap_p4d_supported(void)
  {
        return 0;
index bb9cc5cf087385647f51d4522981d47f317cc45e,80c7992bc53899ce9aa70fcb34dc2e630eabdcc0..60d81fae06eeae154c0a8aa87ca9e56f3345500c
@@@ -103,39 -103,42 +103,42 @@@ static ssize_t align_show(struct devic
        return sprintf(buf, "%ld\n", nd_pfn->align);
  }
  
- static const unsigned long *nd_pfn_supported_alignments(void)
+ static unsigned long *nd_pfn_supported_alignments(unsigned long *alignments)
  {
-       /*
-        * This needs to be a non-static variable because the *_SIZE
-        * macros aren't always constants.
-        */
-       const unsigned long supported_alignments[] = {
-               PAGE_SIZE,
- #ifdef CONFIG_TRANSPARENT_HUGEPAGE
-               HPAGE_PMD_SIZE,
- #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
-               HPAGE_PUD_SIZE,
- #endif
- #endif
-               0,
-       };
-       static unsigned long data[ARRAY_SIZE(supported_alignments)];
  
-       memcpy(data, supported_alignments, sizeof(data));
+       alignments[0] = PAGE_SIZE;
+       if (has_transparent_hugepage()) {
+               alignments[1] = HPAGE_PMD_SIZE;
+               if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD))
+                       alignments[2] = HPAGE_PUD_SIZE;
+       }
+       return alignments;
+ }
+ /*
+  * Use pmd mapping if supported as default alignment
+  */
+ static unsigned long nd_pfn_default_alignment(void)
+ {
  
-       return data;
+       if (has_transparent_hugepage())
+               return HPAGE_PMD_SIZE;
+       return PAGE_SIZE;
  }
  
  static ssize_t align_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
  {
        struct nd_pfn *nd_pfn = to_nd_pfn_safe(dev);
+       unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
        ssize_t rc;
  
        nd_device_lock(dev);
        nvdimm_bus_lock(dev);
        rc = nd_size_select_store(dev, buf, &nd_pfn->align,
-                       nd_pfn_supported_alignments());
+                       nd_pfn_supported_alignments(aligns));
        dev_dbg(dev, "result: %zd wrote: %s%s", rc, buf,
                        buf[len - 1] == '\n' ? "" : "\n");
        nvdimm_bus_unlock(dev);
@@@ -259,7 -262,10 +262,10 @@@ static DEVICE_ATTR_RO(size)
  static ssize_t supported_alignments_show(struct device *dev,
                struct device_attribute *attr, char *buf)
  {
-       return nd_size_select_show(0, nd_pfn_supported_alignments(), buf);
+       unsigned long aligns[MAX_NVDIMM_ALIGN] = { [0] = 0, };
+       return nd_size_select_show(0,
+                       nd_pfn_supported_alignments(aligns), buf);
  }
  static DEVICE_ATTR_RO(supported_alignments);
  
@@@ -302,7 -308,7 +308,7 @@@ struct device *nd_pfn_devinit(struct nd
                return NULL;
  
        nd_pfn->mode = PFN_MODE_NONE;
-       nd_pfn->align = PFN_DEFAULT_ALIGNMENT;
+       nd_pfn->align = nd_pfn_default_alignment();
        dev = &nd_pfn->dev;
        device_initialize(&nd_pfn->dev);
        if (ndns && !__nd_attach_ndns(&nd_pfn->dev, ndns, &nd_pfn->ndns)) {
@@@ -412,6 -418,21 +418,21 @@@ static int nd_pfn_clear_memmap_errors(s
        return 0;
  }
  
+ static bool nd_supported_alignment(unsigned long align)
+ {
+       int i;
+       unsigned long supported[MAX_NVDIMM_ALIGN] = { [0] = 0, };
+       if (align == 0)
+               return false;
+       nd_pfn_supported_alignments(supported);
+       for (i = 0; supported[i]; i++)
+               if (align == supported[i])
+                       return true;
+       return false;
+ }
  /**
   * nd_pfn_validate - read and validate info-block
   * @nd_pfn: fsdax namespace runtime state / properties
@@@ -496,6 -517,18 +517,18 @@@ int nd_pfn_validate(struct nd_pfn *nd_p
                return -EOPNOTSUPP;
        }
  
+       /*
+        * Check whether the we support the alignment. For Dax if the
+        * superblock alignment is not matching, we won't initialize
+        * the device.
+        */
+       if (!nd_supported_alignment(align) &&
+                       !memcmp(pfn_sb->signature, DAX_SIG, PFN_SIG_LEN)) {
+               dev_err(&nd_pfn->dev, "init failed, alignment mismatch: "
+                               "%ld:%ld\n", nd_pfn->align, align);
+               return -EOPNOTSUPP;
+       }
        if (!nd_pfn->uuid) {
                /*
                 * When probing a namepace via nd_pfn_probe() the uuid
@@@ -639,9 -672,11 +672,11 @@@ static int __nvdimm_setup_pfn(struct nd
        struct nd_namespace_common *ndns = nd_pfn->ndns;
        struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
        resource_size_t base = nsio->res.start + start_pad;
+       resource_size_t end = nsio->res.end - end_trunc;
        struct vmem_altmap __altmap = {
                .base_pfn = init_altmap_base(base),
                .reserve = init_altmap_reserve(base),
+               .end_pfn = PHYS_PFN(end),
        };
  
        memcpy(res, &nsio->res, sizeof(*res));
@@@ -676,7 -711,6 +711,7 @@@ static int nd_pfn_init(struct nd_pfn *n
        resource_size_t start, size;
        struct nd_region *nd_region;
        unsigned long npfns, align;
 +      u32 end_trunc;
        struct nd_pfn_sb *pfn_sb;
        phys_addr_t offset;
        const char *sig;
        size = resource_size(&nsio->res);
        npfns = PHYS_PFN(size - SZ_8K);
        align = max(nd_pfn->align, (1UL << SUBSECTION_SHIFT));
 +      end_trunc = start + size - ALIGN_DOWN(start + size, align);
        if (nd_pfn->mode == PFN_MODE_PMEM) {
                /*
                 * The altmap should be padded out to the block size used
                return -ENXIO;
        }
  
 -      npfns = PHYS_PFN(size - offset);
 +      npfns = PHYS_PFN(size - offset - end_trunc);
        pfn_sb->mode = cpu_to_le32(nd_pfn->mode);
        pfn_sb->dataoff = cpu_to_le64(offset);
        pfn_sb->npfns = cpu_to_le64(npfns);
        memcpy(pfn_sb->parent_uuid, nd_dev_to_uuid(&ndns->dev), 16);
        pfn_sb->version_major = cpu_to_le16(1);
        pfn_sb->version_minor = cpu_to_le16(4);
 +      pfn_sb->end_trunc = cpu_to_le32(end_trunc);
        pfn_sb->align = cpu_to_le32(nd_pfn->align);
        pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE);
        pfn_sb->page_size = cpu_to_le32(PAGE_SIZE);
diff --combined include/linux/huge_mm.h
index 61c9ffd89b0521d10d64eecb801a243d16e744f6,376a81ff2c96517dd5294d3d5f0496e27968defc..93d5cf0bc7168fca9aca2179e2e94e3aafd42c43
@@@ -108,7 -108,12 +108,12 @@@ static inline bool __transparent_hugepa
  
        if (transparent_hugepage_flags & (1 << TRANSPARENT_HUGEPAGE_FLAG))
                return true;
+       /*
+        * For dax vmas, try to always use hugepage mappings. If the kernel does
+        * not support hugepages, fsdax mappings will fallback to PAGE_SIZE
+        * mappings, and device-dax namespaces, that try to guarantee a given
+        * mapping size, will fail to enable
+        */
        if (vma_is_dax(vma))
                return true;
  
@@@ -267,15 -272,6 +272,15 @@@ static inline bool thp_migration_suppor
        return IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION);
  }
  
 +static inline struct list_head *page_deferred_list(struct page *page)
 +{
 +      /*
 +       * Global or memcg deferred list in the second tail pages is
 +       * occupied by compound_head.
 +       */
 +      return &page[2].deferred_list;
 +}
 +
  #else /* CONFIG_TRANSPARENT_HUGEPAGE */
  #define HPAGE_PMD_SHIFT ({ BUILD_BUG(); 0; })
  #define HPAGE_PMD_MASK ({ BUILD_BUG(); 0; })
diff --combined include/linux/memremap.h
index bef51e35d8d24b1ece4a0626359b1d36df97a342,c70996fe48c85cac55f20f2fed766405644e2eec..6fefb09af7c34ddc550debf429e6769e77c2cd40
@@@ -17,6 -17,7 +17,7 @@@ struct device
   */
  struct vmem_altmap {
        const unsigned long base_pfn;
+       const unsigned long end_pfn;
        const unsigned long reserve;
        unsigned long free;
        unsigned long align;
@@@ -109,8 -110,10 +110,8 @@@ struct dev_pagemap 
        struct percpu_ref *ref;
        struct percpu_ref internal_ref;
        struct completion done;
 -      struct device *dev;
        enum memory_type type;
        unsigned int flags;
 -      u64 pci_p2pdma_bus_offset;
        const struct dev_pagemap_ops *ops;
  };
  
@@@ -122,8 -125,6 +123,8 @@@ static inline struct vmem_altmap *pgmap
  }
  
  #ifdef CONFIG_ZONE_DEVICE
 +void *memremap_pages(struct dev_pagemap *pgmap, int nid);
 +void memunmap_pages(struct dev_pagemap *pgmap);
  void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap);
  void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap);
  struct dev_pagemap *get_dev_pagemap(unsigned long pfn,
This page took 0.096113 seconds and 4 git commands to generate.