| @@ -13,6 +13,8 @@ · 12 unmodified lines |
| 13 | 13 | #include "pfn.h" |
| 14 | 14 | #include "nd.h" |
| 15 | 15 | |
| 16 | +static const bool page_struct_override = IS_ENABLED(CONFIG_NVDIMM_KMSAN); |
| 17 | + |
| 16 | 18 | static void nd_pfn_release(struct device *dev) |
| 17 | 19 | { |
| 18 | 20 | struct nd_region *nd_region = to_nd_region(dev->parent); |
| @@ -758,12 +760,6 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) · 739 unmodified lines |
| 758 | 760 | return -ENXIO; |
| 759 | 761 | } |
| 760 | 762 | |
| 761 | | − /* |
| 762 | | − * Note, we use 64 here for the standard size of struct page, |
| 763 | | − * debugging options may cause it to be larger in which case the |
| 764 | | − * implementation will limit the pfns advertised through |
| 765 | | − * ->direct_access() to those that are included in the memmap. |
| 766 | | − */ |
| 767 | 763 | start = nsio->res.start; |
| 768 | 764 | size = resource_size(&nsio->res); |
| 769 | 765 | npfns = PHYS_PFN(size - SZ_8K); |
| @@ -782,20 +778,33 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) · 12 unmodified lines |
| 782 | 778 | } |
| 783 | 779 | end_trunc = start + size - ALIGN_DOWN(start + size, align); |
| 784 | 780 | if (nd_pfn->mode == PFN_MODE_PMEM) { |
| 781 | + unsigned long page_map_size = MAX_STRUCT_PAGE_SIZE * npfns; |
| 782 | + |
| 785 | 783 | /* |
| 786 | 784 | * The altmap should be padded out to the block size used |
| 787 | 785 | * when populating the vmemmap. This *should* be equal to |
| 788 | 786 | * PMD_SIZE for most architectures. |
| 789 | 787 | * |
| 790 | | − * Also make sure size of struct page is less than 128. We |
| 791 | | − * want to make sure we use large enough size here so that |
| 792 | | − * we don't have a dynamic reserve space depending on |
| 793 | | − * struct page size. But we also want to make sure we notice |
| 794 | | − * when we end up adding new elements to struct page. |
| 788 | + * Also make sure size of struct page is less than |
| 789 | + * MAX_STRUCT_PAGE_SIZE. The goal here is compatibility in the |
| 790 | + * face of production kernel configurations that reduce the |
| 791 | + * 'struct page' size below MAX_STRUCT_PAGE_SIZE. For debug |
| 792 | + * kernel configurations that increase the 'struct page' size |
| 793 | + * above MAX_STRUCT_PAGE_SIZE, the page_struct_override allows |
| 794 | + * for continuing with the capacity that will be wasted when |
| 795 | + * reverting to a production kernel configuration. Otherwise, |
| 796 | + * those configurations are blocked by default. |
| 795 | 797 | */ |
| 796 | | − BUILD_BUG_ON(sizeof(struct page) > MAX_STRUCT_PAGE_SIZE); |
| 797 | | − offset = ALIGN(start + SZ_8K + MAX_STRUCT_PAGE_SIZE * npfns, align) |
| 798 | | − - start; |
| 798 | + if (sizeof(struct page) > MAX_STRUCT_PAGE_SIZE) { |
| 799 | + if (page_struct_override) |
| 800 | + page_map_size = sizeof(struct page) * npfns; |
| 801 | + else { |
| 802 | + dev_err(&nd_pfn->dev, |
| 803 | + "Memory debug options prevent using pmem for the page map\n"); |
| 804 | + return -EINVAL; |
| 805 | + } |
| 806 | + } |
| 807 | + offset = ALIGN(start + SZ_8K + page_map_size, align) - start; |
| 799 | 808 | } else if (nd_pfn->mode == PFN_MODE_RAM) |
| 800 | 809 | offset = ALIGN(start + SZ_8K, align) - start; |
| 801 | 810 | else |
| @@ -818,7 +827,10 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn) · 16 unmodified lines |
| 818 | 827 | pfn_sb->version_minor = cpu_to_le16(4); |
| 819 | 828 | pfn_sb->end_trunc = cpu_to_le32(end_trunc); |
| 820 | 829 | pfn_sb->align = cpu_to_le32(nd_pfn->align); |
| 821 | | − pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE); |
| 830 | + if (sizeof(struct page) > MAX_STRUCT_PAGE_SIZE && page_struct_override) |
| 831 | + pfn_sb->page_struct_size = cpu_to_le16(sizeof(struct page)); |
| 832 | + else |
| 833 | + pfn_sb->page_struct_size = cpu_to_le16(MAX_STRUCT_PAGE_SIZE); |
| 822 | 834 | pfn_sb->page_size = cpu_to_le32(PAGE_SIZE); |
| 823 | 835 | checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb); |
| 824 | 836 | pfn_sb->checksum = cpu_to_le64(checksum); |