diff mbox series

[v2,1/2] hugetlb: arm64: add mte support

Message ID 20240821184752.3535276-1-yang@os.amperecomputing.com (mailing list archive)
State New
Headers show
Series [v2,1/2] hugetlb: arm64: add mte support | expand

Commit Message

Yang Shi Aug. 21, 2024, 6:47 p.m. UTC
Enable MTE support for hugetlb.

The MTE page flags will be set on the head page only.  When copying
hugetlb folio, the tags for all tail pages will be copied when copying
head page.

When freeing hugetlb folio, the MTE flags will be cleared.

Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
---
 arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
 arch/arm64/include/asm/mman.h    |  3 ++-
 arch/arm64/kernel/hibernate.c    |  7 +++++++
 arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
 arch/arm64/kvm/guest.c           | 16 +++++++++++++---
 arch/arm64/kvm/mmu.c             | 11 +++++++++++
 arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
 fs/hugetlbfs/inode.c             |  2 +-
 8 files changed, 90 insertions(+), 10 deletions(-)

v2: * Reimplemented the patch to fix the comments from Catalin.
    * Added test cases (patch #2) per Catalin.

Comments

kernel test robot Aug. 26, 2024, 11:15 a.m. UTC | #1
Hi Yang,

kernel test robot noticed the following build errors:

[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on kvmarm/next akpm-mm/mm-everything linus/master v6.11-rc5 next-20240823]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Yang-Shi/selftests-arm64-add-hugetlb-mte-tests/20240822-024935
base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
patch link:    https://lore.kernel.org/r/20240821184752.3535276-1-yang%40os.amperecomputing.com
patch subject: [v2 PATCH 1/2] hugetlb: arm64: add mte support
config: arm64-randconfig-004-20240824 (https://download.01.org/0day-ci/archive/20240826/202408261816.ACEJvgZw-lkp@intel.com/config)
compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project 08e5a1de8227512d4774a534b91cb2353cef6284)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240826/202408261816.ACEJvgZw-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202408261816.ACEJvgZw-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from mm/gup.c:7:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/gup.c:18:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   In file included from mm/gup.c:20:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   6 warnings and 1 error generated.
--
   In file included from mm/swap.c:17:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/swap.c:26:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   In file included from mm/swap.c:36:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   6 warnings and 1 error generated.
--
   In file included from mm/shmem.c:28:
   In file included from include/linux/ramfs.h:5:
   In file included from include/linux/fs_parser.h:11:
   In file included from include/linux/fs_context.h:14:
   In file included from include/linux/security.h:33:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/shmem.c:39:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   In file included from mm/shmem.c:58:
   include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
     158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
     159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   6 warnings and 1 error generated.
--
   In file included from mm/mprotect.c:12:
   In file included from include/linux/pagewalk.h:5:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/mprotect.c:13:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   In file included from mm/mprotect.c:15:
   include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
     158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
     159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   In file included from mm/mprotect.c:30:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   8 warnings and 1 error generated.
--
   In file included from mm/show_mem.c:8:
   In file included from include/linux/blkdev.h:9:
   In file included from include/linux/blk_types.h:10:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:8:
   In file included from include/linux/cacheflush.h:5:
   In file included from arch/arm64/include/asm/cacheflush.h:11:
   In file included from include/linux/kgdb.h:19:
   In file included from include/linux/kprobes.h:28:
   In file included from include/linux/ftrace.h:13:
   In file included from include/linux/kallsyms.h:13:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/show_mem.c:12:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   4 warnings and 1 error generated.
--
   In file included from mm/mremap.c:11:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/mremap.c:12:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   In file included from mm/mremap.c:13:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   In file included from mm/mremap.c:16:
   include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
     158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
     159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   8 warnings and 1 error generated.
--
   In file included from mm/huge_memory.c:8:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/huge_memory.c:14:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   In file included from mm/huge_memory.c:19:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   In file included from mm/huge_memory.c:27:
   include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
     158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
     159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
     136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
         |                     ^ ~~~~~~~~~~~~~~~~~
   8 warnings and 1 error generated.
--
   In file included from mm/vmscan.c:15:
   In file included from include/linux/mm.h:2228:
   include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     501 |                            item];
         |                            ~~~~
   include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     508 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
         |                               ~~~~~~~~~~~ ^ ~~~
   include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
     519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~ ^
     520 |                            NR_VM_NUMA_EVENT_ITEMS +
         |                            ~~~~~~~~~~~~~~~~~~~~~~
   In file included from mm/vmscan.c:30:
   include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
         |                                    ~~~~~~~~~~~ ^ ~~~
   include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
      49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
         |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
   In file included from mm/vmscan.c:42:
   In file included from include/linux/migrate.h:8:
   In file included from include/linux/hugetlb.h:798:
>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
      25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
         |                                          ^
   mm/vmscan.c:401:51: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
     401 |                         size += zone_page_state(zone, NR_ZONE_LRU_BASE + lru);
         |                                                       ~~~~~~~~~~~~~~~~ ^ ~~~
   mm/vmscan.c:1729:4: warning: arithmetic between different enumeration types ('enum vm_event_item' and 'enum zone_type') [-Wenum-enum-conversion]
    1729 |                         __count_zid_vm_events(PGSCAN_SKIP, zid, nr_skipped[zid]);
         |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:135:34: note: expanded from macro '__count_zid_vm_events'
     135 |         __count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)
         |                           ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
   mm/vmscan.c:2232:51: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
    2232 |         inactive = lruvec_page_state(lruvec, NR_LRU_BASE + inactive_lru);
         |                                              ~~~~~~~~~~~ ^ ~~~~~~~~~~~~
   mm/vmscan.c:2233:49: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
    2233 |         active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru);
         |                                            ~~~~~~~~~~~ ^ ~~~~~~~~~~
   mm/vmscan.c:6247:3: warning: arithmetic between different enumeration types ('enum vm_event_item' and 'enum zone_type') [-Wenum-enum-conversion]
    6247 |                 __count_zid_vm_events(ALLOCSTALL, sc->reclaim_idx, 1);
         |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   include/linux/vmstat.h:135:34: note: expanded from macro '__count_zid_vm_events'
     135 |         __count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)
         |                           ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
   11 warnings and 1 error generated.
..


vim +/PG_mte_lock +25 arch/arm64/include/asm/hugetlb.h

    21	
    22	static inline void arch_clear_hugetlb_flags(struct folio *folio)
    23	{
    24		const unsigned long clear_flags = BIT(PG_dcache_clean) |
  > 25			BIT(PG_mte_tagged) | BIT(PG_mte_lock);
    26	
    27		if (!system_supports_mte()) {
    28			clear_bit(PG_dcache_clean, &folio->flags);
    29			return;
    30		}
    31	
    32		folio->flags &= ~clear_flags;
    33	}
    34	#define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
    35
Yang Shi Aug. 26, 2024, 5:02 p.m. UTC | #2
On 8/26/24 4:15 AM, kernel test robot wrote:
> Hi Yang,
>
> kernel test robot noticed the following build errors:
>
> [auto build test ERROR on arm64/for-next/core]
> [also build test ERROR on kvmarm/next akpm-mm/mm-everything linus/master v6.11-rc5 next-20240823]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
>
> url:    https://github.com/intel-lab-lkp/linux/commits/Yang-Shi/selftests-arm64-add-hugetlb-mte-tests/20240822-024935
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core
> patch link:    https://lore.kernel.org/r/20240821184752.3535276-1-yang%40os.amperecomputing.com
> patch subject: [v2 PATCH 1/2] hugetlb: arm64: add mte support
> config: arm64-randconfig-004-20240824 (https://download.01.org/0day-ci/archive/20240826/202408261816.ACEJvgZw-lkp@intel.com/config)
> compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project 08e5a1de8227512d4774a534b91cb2353cef6284)
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240826/202408261816.ACEJvgZw-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202408261816.ACEJvgZw-lkp@intel.com/
>
> All errors (new ones prefixed by >>):
>
>     In file included from mm/gup.c:7:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/gup.c:18:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);

Thanks for the report. It is because the config has CONFIG_MTE disabled. 
I will fix this. But I'd prefer the response from the maintainers then 
fix all them together.

>           |                                          ^
>     In file included from mm/gup.c:20:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     6 warnings and 1 error generated.
> --
>     In file included from mm/swap.c:17:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/swap.c:26:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     In file included from mm/swap.c:36:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     6 warnings and 1 error generated.
> --
>     In file included from mm/shmem.c:28:
>     In file included from include/linux/ramfs.h:5:
>     In file included from include/linux/fs_parser.h:11:
>     In file included from include/linux/fs_context.h:14:
>     In file included from include/linux/security.h:33:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/shmem.c:39:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     In file included from mm/shmem.c:58:
>     include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     6 warnings and 1 error generated.
> --
>     In file included from mm/mprotect.c:12:
>     In file included from include/linux/pagewalk.h:5:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/mprotect.c:13:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     In file included from mm/mprotect.c:15:
>     include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     In file included from mm/mprotect.c:30:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     8 warnings and 1 error generated.
> --
>     In file included from mm/show_mem.c:8:
>     In file included from include/linux/blkdev.h:9:
>     In file included from include/linux/blk_types.h:10:
>     In file included from include/linux/bvec.h:10:
>     In file included from include/linux/highmem.h:8:
>     In file included from include/linux/cacheflush.h:5:
>     In file included from arch/arm64/include/asm/cacheflush.h:11:
>     In file included from include/linux/kgdb.h:19:
>     In file included from include/linux/kprobes.h:28:
>     In file included from include/linux/ftrace.h:13:
>     In file included from include/linux/kallsyms.h:13:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/show_mem.c:12:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     4 warnings and 1 error generated.
> --
>     In file included from mm/mremap.c:11:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/mremap.c:12:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     In file included from mm/mremap.c:13:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     In file included from mm/mremap.c:16:
>     include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     8 warnings and 1 error generated.
> --
>     In file included from mm/huge_memory.c:8:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/huge_memory.c:14:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     In file included from mm/huge_memory.c:19:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     In file included from mm/huge_memory.c:27:
>     include/linux/mman.h:158:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       158 |                _calc_vm_trans(flags, MAP_SYNC,       VM_SYNC      ) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:159:9: warning: division by zero is undefined [-Wdivision-by-zero]
>       159 |                _calc_vm_trans(flags, MAP_STACK,      VM_NOHUGEPAGE) |
>           |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/mman.h:136:21: note: expanded from macro '_calc_vm_trans'
>       136 |    : ((x) & (bit1)) / ((bit1) / (bit2))))
>           |                     ^ ~~~~~~~~~~~~~~~~~
>     8 warnings and 1 error generated.
> --
>     In file included from mm/vmscan.c:15:
>     In file included from include/linux/mm.h:2228:
>     include/linux/vmstat.h:500:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       500 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       501 |                            item];
>           |                            ~~~~
>     include/linux/vmstat.h:507:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       507 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       508 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:514:36: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       514 |         return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
>           |                               ~~~~~~~~~~~ ^ ~~~
>     include/linux/vmstat.h:519:43: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum numa_stat_item') [-Wenum-enum-conversion]
>       519 |         return vmstat_text[NR_VM_ZONE_STAT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~ ^
>       520 |                            NR_VM_NUMA_EVENT_ITEMS +
>           |                            ~~~~~~~~~~~~~~~~~~~~~~
>     In file included from mm/vmscan.c:30:
>     include/linux/mm_inline.h:47:41: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        47 |         __mod_lruvec_state(lruvec, NR_LRU_BASE + lru, nr_pages);
>           |                                    ~~~~~~~~~~~ ^ ~~~
>     include/linux/mm_inline.h:49:22: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>        49 |                                 NR_ZONE_LRU_BASE + lru, nr_pages);
>           |                                 ~~~~~~~~~~~~~~~~ ^ ~~~
>     In file included from mm/vmscan.c:42:
>     In file included from include/linux/migrate.h:8:
>     In file included from include/linux/hugetlb.h:798:
>>> arch/arm64/include/asm/hugetlb.h:25:28: error: use of undeclared identifier 'PG_mte_lock'
>        25 |                 BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>           |                                          ^
>     mm/vmscan.c:401:51: warning: arithmetic between different enumeration types ('enum zone_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>       401 |                         size += zone_page_state(zone, NR_ZONE_LRU_BASE + lru);
>           |                                                       ~~~~~~~~~~~~~~~~ ^ ~~~
>     mm/vmscan.c:1729:4: warning: arithmetic between different enumeration types ('enum vm_event_item' and 'enum zone_type') [-Wenum-enum-conversion]
>      1729 |                         __count_zid_vm_events(PGSCAN_SKIP, zid, nr_skipped[zid]);
>           |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:135:34: note: expanded from macro '__count_zid_vm_events'
>       135 |         __count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)
>           |                           ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
>     mm/vmscan.c:2232:51: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>      2232 |         inactive = lruvec_page_state(lruvec, NR_LRU_BASE + inactive_lru);
>           |                                              ~~~~~~~~~~~ ^ ~~~~~~~~~~~~
>     mm/vmscan.c:2233:49: warning: arithmetic between different enumeration types ('enum node_stat_item' and 'enum lru_list') [-Wenum-enum-conversion]
>      2233 |         active = lruvec_page_state(lruvec, NR_LRU_BASE + active_lru);
>           |                                            ~~~~~~~~~~~ ^ ~~~~~~~~~~
>     mm/vmscan.c:6247:3: warning: arithmetic between different enumeration types ('enum vm_event_item' and 'enum zone_type') [-Wenum-enum-conversion]
>      6247 |                 __count_zid_vm_events(ALLOCSTALL, sc->reclaim_idx, 1);
>           |                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>     include/linux/vmstat.h:135:34: note: expanded from macro '__count_zid_vm_events'
>       135 |         __count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)
>           |                           ~~~~~~~~~~~~~ ^ ~~~~~~~~~~~
>     11 warnings and 1 error generated.
> ..
>
>
> vim +/PG_mte_lock +25 arch/arm64/include/asm/hugetlb.h
>
>      21	
>      22	static inline void arch_clear_hugetlb_flags(struct folio *folio)
>      23	{
>      24		const unsigned long clear_flags = BIT(PG_dcache_clean) |
>    > 25			BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>      26	
>      27		if (!system_supports_mte()) {
>      28			clear_bit(PG_dcache_clean, &folio->flags);
>      29			return;
>      30		}
>      31	
>      32		folio->flags &= ~clear_flags;
>      33	}
>      34	#define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>      35	
>
Yang Shi Aug. 28, 2024, 5:57 p.m. UTC | #3
On 8/21/24 11:47 AM, Yang Shi wrote:
> Enable MTE support for hugetlb.
>
> The MTE page flags will be set on the head page only.  When copying
> hugetlb folio, the tags for all tail pages will be copied when copying
> head page.
>
> When freeing hugetlb folio, the MTE flags will be cleared.
>
> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
> ---
>   arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>   arch/arm64/include/asm/mman.h    |  3 ++-
>   arch/arm64/kernel/hibernate.c    |  7 +++++++
>   arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>   arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>   arch/arm64/kvm/mmu.c             | 11 +++++++++++
>   arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>   fs/hugetlbfs/inode.c             |  2 +-
>   8 files changed, 90 insertions(+), 10 deletions(-)
>
> v2: * Reimplemented the patch to fix the comments from Catalin.
>      * Added test cases (patch #2) per Catalin.

Ping... Is there any comment on this version?

Thanks,
Yang

>
> diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
> index 293f880865e8..00a1f75d40ee 100644
> --- a/arch/arm64/include/asm/hugetlb.h
> +++ b/arch/arm64/include/asm/hugetlb.h
> @@ -11,6 +11,7 @@
>   #define __ASM_HUGETLB_H
>   
>   #include <asm/cacheflush.h>
> +#include <asm/mte.h>
>   #include <asm/page.h>
>   
>   #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
> @@ -20,7 +21,15 @@ extern bool arch_hugetlb_migration_supported(struct hstate *h);
>   
>   static inline void arch_clear_hugetlb_flags(struct folio *folio)
>   {
> -	clear_bit(PG_dcache_clean, &folio->flags);
> +	const unsigned long clear_flags = BIT(PG_dcache_clean) |
> +		BIT(PG_mte_tagged) | BIT(PG_mte_lock);
> +
> +	if (!system_supports_mte()) {
> +		clear_bit(PG_dcache_clean, &folio->flags);
> +		return;
> +	}
> +
> +	folio->flags &= ~clear_flags;
>   }
>   #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>   
> diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
> index 5966ee4a6154..304dfc499e68 100644
> --- a/arch/arm64/include/asm/mman.h
> +++ b/arch/arm64/include/asm/mman.h
> @@ -28,7 +28,8 @@ static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
>   	 * backed by tags-capable memory. The vm_flags may be overridden by a
>   	 * filesystem supporting MTE (RAM-based).
>   	 */
> -	if (system_supports_mte() && (flags & MAP_ANONYMOUS))
> +	if (system_supports_mte() &&
> +	    (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>   		return VM_MTE_ALLOWED;
>   
>   	return 0;
> diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
> index 02870beb271e..722e76f29141 100644
> --- a/arch/arm64/kernel/hibernate.c
> +++ b/arch/arm64/kernel/hibernate.c
> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>   		max_zone_pfn = zone_end_pfn(zone);
>   		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
>   			struct page *page = pfn_to_online_page(pfn);
> +			struct folio *folio;
>   
>   			if (!page)
>   				continue;
>   
> +			folio = page_folio(page);
> +
> +			if (folio_test_hugetlb(folio) &&
> +			    !page_mte_tagged(&folio->page))
> +				continue;
> +
>   			if (!page_mte_tagged(page))
>   				continue;
>   
> diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> index 6174671be7c1..b21f706018f7 100644
> --- a/arch/arm64/kernel/mte.c
> +++ b/arch/arm64/kernel/mte.c
> @@ -38,7 +38,22 @@ EXPORT_SYMBOL_GPL(mte_async_or_asymm_mode);
>   void mte_sync_tags(pte_t pte, unsigned int nr_pages)
>   {
>   	struct page *page = pte_page(pte);
> -	unsigned int i;
> +	struct folio *folio = page_folio(page);
> +	unsigned long i;
> +
> +	if (folio_test_hugetlb(folio)) {
> +		unsigned long nr = folio_nr_pages(folio);
> +		/* Hugetlb MTE flags are set for head page only */
> +		if (try_page_mte_tagging(&folio->page)) {
> +			for (i = 0; i < nr; i++, page++)
> +				mte_clear_page_tags(page_address(page));
> +			set_page_mte_tagged(&folio->page);
> +		}
> +
> +		smp_wmb();
> +
> +		return;
> +	}
>   
>   	/* if PG_mte_tagged is set, tags have already been initialised */
>   	for (i = 0; i < nr_pages; i++, page++) {
> @@ -410,6 +425,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
>   		void *maddr;
>   		struct page *page = get_user_page_vma_remote(mm, addr,
>   							     gup_flags, &vma);
> +		struct folio *folio;
>   
>   		if (IS_ERR(page)) {
>   			err = PTR_ERR(page);
> @@ -428,7 +444,12 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
>   			put_page(page);
>   			break;
>   		}
> -		WARN_ON_ONCE(!page_mte_tagged(page));
> +
> +		folio = page_folio(page);
> +		if (folio_test_hugetlb(folio))
> +			WARN_ON_ONCE(!page_mte_tagged(&folio->page));
> +		else
> +			WARN_ON_ONCE(!page_mte_tagged(page));
>   
>   		/* limit access to the end of the page */
>   		offset = offset_in_page(addr);
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 11098eb7eb44..77e181d96e97 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -1050,6 +1050,7 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>   		void *maddr;
>   		unsigned long num_tags;
>   		struct page *page;
> +		struct folio *folio;
>   
>   		if (is_error_noslot_pfn(pfn)) {
>   			ret = -EFAULT;
> @@ -1062,10 +1063,13 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>   			ret = -EFAULT;
>   			goto out;
>   		}
> +		folio = page_folio(page);
>   		maddr = page_address(page);
>   
>   		if (!write) {
> -			if (page_mte_tagged(page))
> +			if (page_mte_tagged(page) ||
> +			    (folio_test_hugetlb(folio) &&
> +			     page_mte_tagged(&folio->page)))
>   				num_tags = mte_copy_tags_to_user(tags, maddr,
>   							MTE_GRANULES_PER_PAGE);
>   			else
> @@ -1079,14 +1083,20 @@ int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
>   			 * __set_ptes() in the VMM but still overriding the
>   			 * tags, hence ignoring the return value.
>   			 */
> -			try_page_mte_tagging(page);
> +			if (folio_test_hugetlb(folio))
> +				try_page_mte_tagging(&folio->page);
> +			else
> +				try_page_mte_tagging(page);
>   			num_tags = mte_copy_tags_from_user(maddr, tags,
>   							MTE_GRANULES_PER_PAGE);
>   
>   			/* uaccess failed, don't leave stale tags */
>   			if (num_tags != MTE_GRANULES_PER_PAGE)
>   				mte_clear_page_tags(maddr);
> -			set_page_mte_tagged(page);
> +			if (folio_test_hugetlb(folio))
> +				set_page_mte_tagged(&folio->page);
> +			else
> +				set_page_mte_tagged(page);
>   
>   			kvm_release_pfn_dirty(pfn);
>   		}
> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
> index 6981b1bc0946..1fa51ac4e3f4 100644
> --- a/arch/arm64/kvm/mmu.c
> +++ b/arch/arm64/kvm/mmu.c
> @@ -1401,10 +1401,21 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
>   {
>   	unsigned long i, nr_pages = size >> PAGE_SHIFT;
>   	struct page *page = pfn_to_page(pfn);
> +	struct folio *folio = page_folio(page);
>   
>   	if (!kvm_has_mte(kvm))
>   		return;
>   
> +	if (folio_test_hugetlb(folio)) {
> +		/* Hugetlb has MTE flags set on head page only */
> +		if (try_page_mte_tagging(&folio->page)) {
> +			for (i = 0; i < nr_pages; i++, page++)
> +				mte_clear_page_tags(page_address(page));
> +			set_page_mte_tagged(&folio->page);
> +		}
> +		return;
> +	}
> +
>   	for (i = 0; i < nr_pages; i++, page++) {
>   		if (try_page_mte_tagging(page)) {
>   			mte_clear_page_tags(page_address(page));
> diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
> index a7bb20055ce0..0f3b07d4a5cf 100644
> --- a/arch/arm64/mm/copypage.c
> +++ b/arch/arm64/mm/copypage.c
> @@ -18,6 +18,9 @@ void copy_highpage(struct page *to, struct page *from)
>   {
>   	void *kto = page_address(to);
>   	void *kfrom = page_address(from);
> +	struct folio *src = page_folio(from);
> +	struct folio *dst = page_folio(to);
> +	unsigned int i, nr_pages;
>   
>   	copy_page(kto, kfrom);
>   
> @@ -27,8 +30,26 @@ void copy_highpage(struct page *to, struct page *from)
>   	if (system_supports_mte() && page_mte_tagged(from)) {
>   		/* It's a new page, shouldn't have been tagged yet */
>   		WARN_ON_ONCE(!try_page_mte_tagging(to));
> -		mte_copy_page_tags(kto, kfrom);
> -		set_page_mte_tagged(to);
> +
> +		/* Populate tags for all subpages if hugetlb */
> +		if (folio_test_hugetlb(src)) {
> +			/*
> +			 * MTE page flag is just set on the head page of
> +			 * hugetlb. If from has MTE flag set, it must be the
> +			 * head page.
> +			 */
> +			VM_BUG_ON(!PageHead(from));
> +			nr_pages = folio_nr_pages(src);
> +			for (i = 0; i < nr_pages; i++, to++, from++) {
> +				kto = page_address(to);
> +				kfrom = page_address(from);
> +				mte_copy_page_tags(kto, kfrom);
> +			}
> +			set_page_mte_tagged(&dst->page);
> +		} else {
> +			mte_copy_page_tags(kto, kfrom);
> +			set_page_mte_tagged(to);
> +		}
>   	}
>   }
>   EXPORT_SYMBOL(copy_highpage);
> diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
> index 9f6cff356796..f944e8e7126b 100644
> --- a/fs/hugetlbfs/inode.c
> +++ b/fs/hugetlbfs/inode.c
> @@ -110,7 +110,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
>   	 * way when do_mmap unwinds (may be important on powerpc
>   	 * and ia64).
>   	 */
> -	vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND);
> +	vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND | VM_MTE_ALLOWED);
>   	vma->vm_ops = &hugetlb_vm_ops;
>   
>   	ret = seal_check_write(info->seals, vma);
David Hildenbrand Sept. 2, 2024, 2:33 p.m. UTC | #4
On 21.08.24 20:47, Yang Shi wrote:
> Enable MTE support for hugetlb.
> 
> The MTE page flags will be set on the head page only.  When copying
> hugetlb folio, the tags for all tail pages will be copied when copying
> head page.
> 
> When freeing hugetlb folio, the MTE flags will be cleared.
> 
> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
> ---
>   arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>   arch/arm64/include/asm/mman.h    |  3 ++-
>   arch/arm64/kernel/hibernate.c    |  7 +++++++
>   arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>   arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>   arch/arm64/kvm/mmu.c             | 11 +++++++++++
>   arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>   fs/hugetlbfs/inode.c             |  2 +-
>   8 files changed, 90 insertions(+), 10 deletions(-)
> 
> v2: * Reimplemented the patch to fix the comments from Catalin.
>      * Added test cases (patch #2) per Catalin.
> 
> diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
> index 293f880865e8..00a1f75d40ee 100644
> --- a/arch/arm64/include/asm/hugetlb.h
> +++ b/arch/arm64/include/asm/hugetlb.h
> @@ -11,6 +11,7 @@
>   #define __ASM_HUGETLB_H
>   
>   #include <asm/cacheflush.h>
> +#include <asm/mte.h>
>   #include <asm/page.h>
>   
>   #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
> @@ -20,7 +21,15 @@ extern bool arch_hugetlb_migration_supported(struct hstate *h);
>   
>   static inline void arch_clear_hugetlb_flags(struct folio *folio)
>   {
> -	clear_bit(PG_dcache_clean, &folio->flags);
> +	const unsigned long clear_flags = BIT(PG_dcache_clean) |
> +		BIT(PG_mte_tagged) | BIT(PG_mte_lock);
> +
> +	if (!system_supports_mte()) {
> +		clear_bit(PG_dcache_clean, &folio->flags);
> +		return;
> +	}
> +
> +	folio->flags &= ~clear_flags;
>   }
>   #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>   
> diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
> index 5966ee4a6154..304dfc499e68 100644
> --- a/arch/arm64/include/asm/mman.h
> +++ b/arch/arm64/include/asm/mman.h
> @@ -28,7 +28,8 @@ static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
>   	 * backed by tags-capable memory. The vm_flags may be overridden by a
>   	 * filesystem supporting MTE (RAM-based).
>   	 */
> -	if (system_supports_mte() && (flags & MAP_ANONYMOUS))
> +	if (system_supports_mte() &&
> +	    (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>   		return VM_MTE_ALLOWED;
>   
>   	return 0;
> diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
> index 02870beb271e..722e76f29141 100644
> --- a/arch/arm64/kernel/hibernate.c
> +++ b/arch/arm64/kernel/hibernate.c
> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>   		max_zone_pfn = zone_end_pfn(zone);
>   		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
>   			struct page *page = pfn_to_online_page(pfn);
> +			struct folio *folio;
>   
>   			if (!page)
>   				continue;
>   
> +			folio = page_folio(page);
> +
> +			if (folio_test_hugetlb(folio) &&
> +			    !page_mte_tagged(&folio->page))
> +				continue;

Can we have folio_test_mte_tagged() whereby you make sure that only 
folio_test_hugetlb() uses it for now (VM_WARN_ON_ONCE) and then make 
sure that nobody uses page_mte_tagged() on hugetlb folios (VM_WARN_ON_ONCE)?

Same for folio_set_mte_tagged() and other functions. We could slap a 
"hugetlb" into the function names, but maybe in the future we'll be able 
to use a single flag per folio (I know, it's complicated ...).
Yang Shi Sept. 3, 2024, 4:46 p.m. UTC | #5
On 9/2/24 7:33 AM, David Hildenbrand wrote:
> On 21.08.24 20:47, Yang Shi wrote:
>> Enable MTE support for hugetlb.
>>
>> The MTE page flags will be set on the head page only.  When copying
>> hugetlb folio, the tags for all tail pages will be copied when copying
>> head page.
>>
>> When freeing hugetlb folio, the MTE flags will be cleared.
>>
>> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
>> ---
>>   arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>>   arch/arm64/include/asm/mman.h    |  3 ++-
>>   arch/arm64/kernel/hibernate.c    |  7 +++++++
>>   arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>>   arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>>   arch/arm64/kvm/mmu.c             | 11 +++++++++++
>>   arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>>   fs/hugetlbfs/inode.c             |  2 +-
>>   8 files changed, 90 insertions(+), 10 deletions(-)
>>
>> v2: * Reimplemented the patch to fix the comments from Catalin.
>>      * Added test cases (patch #2) per Catalin.
>>
>> diff --git a/arch/arm64/include/asm/hugetlb.h 
>> b/arch/arm64/include/asm/hugetlb.h
>> index 293f880865e8..00a1f75d40ee 100644
>> --- a/arch/arm64/include/asm/hugetlb.h
>> +++ b/arch/arm64/include/asm/hugetlb.h
>> @@ -11,6 +11,7 @@
>>   #define __ASM_HUGETLB_H
>>     #include <asm/cacheflush.h>
>> +#include <asm/mte.h>
>>   #include <asm/page.h>
>>     #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
>> @@ -20,7 +21,15 @@ extern bool 
>> arch_hugetlb_migration_supported(struct hstate *h);
>>     static inline void arch_clear_hugetlb_flags(struct folio *folio)
>>   {
>> -    clear_bit(PG_dcache_clean, &folio->flags);
>> +    const unsigned long clear_flags = BIT(PG_dcache_clean) |
>> +        BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>> +
>> +    if (!system_supports_mte()) {
>> +        clear_bit(PG_dcache_clean, &folio->flags);
>> +        return;
>> +    }
>> +
>> +    folio->flags &= ~clear_flags;
>>   }
>>   #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>>   diff --git a/arch/arm64/include/asm/mman.h 
>> b/arch/arm64/include/asm/mman.h
>> index 5966ee4a6154..304dfc499e68 100644
>> --- a/arch/arm64/include/asm/mman.h
>> +++ b/arch/arm64/include/asm/mman.h
>> @@ -28,7 +28,8 @@ static inline unsigned long 
>> arch_calc_vm_flag_bits(unsigned long flags)
>>        * backed by tags-capable memory. The vm_flags may be 
>> overridden by a
>>        * filesystem supporting MTE (RAM-based).
>>        */
>> -    if (system_supports_mte() && (flags & MAP_ANONYMOUS))
>> +    if (system_supports_mte() &&
>> +        (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>>           return VM_MTE_ALLOWED;
>>         return 0;
>> diff --git a/arch/arm64/kernel/hibernate.c 
>> b/arch/arm64/kernel/hibernate.c
>> index 02870beb271e..722e76f29141 100644
>> --- a/arch/arm64/kernel/hibernate.c
>> +++ b/arch/arm64/kernel/hibernate.c
>> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>>           max_zone_pfn = zone_end_pfn(zone);
>>           for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
>>               struct page *page = pfn_to_online_page(pfn);
>> +            struct folio *folio;
>>                 if (!page)
>>                   continue;
>>   +            folio = page_folio(page);
>> +
>> +            if (folio_test_hugetlb(folio) &&
>> +                !page_mte_tagged(&folio->page))
>> +                continue;
>
> Can we have folio_test_mte_tagged() whereby you make sure that only 
> folio_test_hugetlb() uses it for now (VM_WARN_ON_ONCE) and then make 
> sure that nobody uses page_mte_tagged() on hugetlb folios 
> (VM_WARN_ON_ONCE)?


IIUC, you mean something like the below?

bool folio_test_mte_tagged(struct folio *folio)
{
     VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));

     return test_bit(PG_mte_tagged, &folio->page->flags);
}

bool page_mte_tagged(struct page *page)
{
     struct folio *folio = page_folio(page);

     VM_WARN_ON_ONCE(folio_test_hugetlb(folio));

     return test_bit(PG_mte_tagged, &pge->flags);
}

>
> Same for folio_set_mte_tagged() and other functions. We could slap a 
> "hugetlb" into the function names, but maybe in the future we'll be 
> able to use a single flag per folio (I know, it's complicated ...).

A single flag per folio should be the future direction, but I haven't 
done the research so can't tell how complicated it will be.
David Hildenbrand Sept. 3, 2024, 9:35 p.m. UTC | #6
On 03.09.24 18:46, Yang Shi wrote:
> 
> 
> On 9/2/24 7:33 AM, David Hildenbrand wrote:
>> On 21.08.24 20:47, Yang Shi wrote:
>>> Enable MTE support for hugetlb.
>>>
>>> The MTE page flags will be set on the head page only.  When copying
>>> hugetlb folio, the tags for all tail pages will be copied when copying
>>> head page.
>>>
>>> When freeing hugetlb folio, the MTE flags will be cleared.
>>>
>>> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
>>> ---
>>>    arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>>>    arch/arm64/include/asm/mman.h    |  3 ++-
>>>    arch/arm64/kernel/hibernate.c    |  7 +++++++
>>>    arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>>>    arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>>>    arch/arm64/kvm/mmu.c             | 11 +++++++++++
>>>    arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>>>    fs/hugetlbfs/inode.c             |  2 +-
>>>    8 files changed, 90 insertions(+), 10 deletions(-)
>>>
>>> v2: * Reimplemented the patch to fix the comments from Catalin.
>>>       * Added test cases (patch #2) per Catalin.
>>>
>>> diff --git a/arch/arm64/include/asm/hugetlb.h
>>> b/arch/arm64/include/asm/hugetlb.h
>>> index 293f880865e8..00a1f75d40ee 100644
>>> --- a/arch/arm64/include/asm/hugetlb.h
>>> +++ b/arch/arm64/include/asm/hugetlb.h
>>> @@ -11,6 +11,7 @@
>>>    #define __ASM_HUGETLB_H
>>>      #include <asm/cacheflush.h>
>>> +#include <asm/mte.h>
>>>    #include <asm/page.h>
>>>      #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
>>> @@ -20,7 +21,15 @@ extern bool
>>> arch_hugetlb_migration_supported(struct hstate *h);
>>>      static inline void arch_clear_hugetlb_flags(struct folio *folio)
>>>    {
>>> -    clear_bit(PG_dcache_clean, &folio->flags);
>>> +    const unsigned long clear_flags = BIT(PG_dcache_clean) |
>>> +        BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>>> +
>>> +    if (!system_supports_mte()) {
>>> +        clear_bit(PG_dcache_clean, &folio->flags);
>>> +        return;
>>> +    }
>>> +
>>> +    folio->flags &= ~clear_flags;
>>>    }
>>>    #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>>>    diff --git a/arch/arm64/include/asm/mman.h
>>> b/arch/arm64/include/asm/mman.h
>>> index 5966ee4a6154..304dfc499e68 100644
>>> --- a/arch/arm64/include/asm/mman.h
>>> +++ b/arch/arm64/include/asm/mman.h
>>> @@ -28,7 +28,8 @@ static inline unsigned long
>>> arch_calc_vm_flag_bits(unsigned long flags)
>>>         * backed by tags-capable memory. The vm_flags may be
>>> overridden by a
>>>         * filesystem supporting MTE (RAM-based).
>>>         */
>>> -    if (system_supports_mte() && (flags & MAP_ANONYMOUS))
>>> +    if (system_supports_mte() &&
>>> +        (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>>>            return VM_MTE_ALLOWED;
>>>          return 0;
>>> diff --git a/arch/arm64/kernel/hibernate.c
>>> b/arch/arm64/kernel/hibernate.c
>>> index 02870beb271e..722e76f29141 100644
>>> --- a/arch/arm64/kernel/hibernate.c
>>> +++ b/arch/arm64/kernel/hibernate.c
>>> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>>>            max_zone_pfn = zone_end_pfn(zone);
>>>            for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
>>>                struct page *page = pfn_to_online_page(pfn);
>>> +            struct folio *folio;
>>>                  if (!page)
>>>                    continue;
>>>    +            folio = page_folio(page);
>>> +
>>> +            if (folio_test_hugetlb(folio) &&
>>> +                !page_mte_tagged(&folio->page))
>>> +                continue;
>>
>> Can we have folio_test_mte_tagged() whereby you make sure that only
>> folio_test_hugetlb() uses it for now (VM_WARN_ON_ONCE) and then make
>> sure that nobody uses page_mte_tagged() on hugetlb folios
>> (VM_WARN_ON_ONCE)?
> 
> 
> IIUC, you mean something like the below?
> 
> bool folio_test_mte_tagged(struct folio *folio)
> {
>       VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
> 
>       return test_bit(PG_mte_tagged, &folio->page->flags);

folio->flags

> }
> 
> bool page_mte_tagged(struct page *page)
> {
>       struct folio *folio = page_folio(page);
> 
>       VM_WARN_ON_ONCE(folio_test_hugetlb(folio));

Yes, but better as

VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));

> 
>       return test_bit(PG_mte_tagged, &pge->flags);
> }
> 
>>
>> Same for folio_set_mte_tagged() and other functions. We could slap a
>> "hugetlb" into the function names, but maybe in the future we'll be
>> able to use a single flag per folio (I know, it's complicated ...).
> 
> A single flag per folio should be the future direction, but I haven't
> done the research so can't tell how complicated it will be.

There were some discussions on it, and it's tricky. So maybe we should 
really just have folio_test_hugetlb_mte_tagged() etc. for now
Yang Shi Sept. 4, 2024, 5:57 p.m. UTC | #7
On 9/3/24 2:35 PM, David Hildenbrand wrote:
> On 03.09.24 18:46, Yang Shi wrote:
>>
>>
>> On 9/2/24 7:33 AM, David Hildenbrand wrote:
>>> On 21.08.24 20:47, Yang Shi wrote:
>>>> Enable MTE support for hugetlb.
>>>>
>>>> The MTE page flags will be set on the head page only.  When copying
>>>> hugetlb folio, the tags for all tail pages will be copied when copying
>>>> head page.
>>>>
>>>> When freeing hugetlb folio, the MTE flags will be cleared.
>>>>
>>>> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
>>>> ---
>>>>    arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>>>>    arch/arm64/include/asm/mman.h    |  3 ++-
>>>>    arch/arm64/kernel/hibernate.c    |  7 +++++++
>>>>    arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>>>>    arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>>>>    arch/arm64/kvm/mmu.c             | 11 +++++++++++
>>>>    arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>>>>    fs/hugetlbfs/inode.c             |  2 +-
>>>>    8 files changed, 90 insertions(+), 10 deletions(-)
>>>>
>>>> v2: * Reimplemented the patch to fix the comments from Catalin.
>>>>       * Added test cases (patch #2) per Catalin.
>>>>
>>>> diff --git a/arch/arm64/include/asm/hugetlb.h
>>>> b/arch/arm64/include/asm/hugetlb.h
>>>> index 293f880865e8..00a1f75d40ee 100644
>>>> --- a/arch/arm64/include/asm/hugetlb.h
>>>> +++ b/arch/arm64/include/asm/hugetlb.h
>>>> @@ -11,6 +11,7 @@
>>>>    #define __ASM_HUGETLB_H
>>>>      #include <asm/cacheflush.h>
>>>> +#include <asm/mte.h>
>>>>    #include <asm/page.h>
>>>>      #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
>>>> @@ -20,7 +21,15 @@ extern bool
>>>> arch_hugetlb_migration_supported(struct hstate *h);
>>>>      static inline void arch_clear_hugetlb_flags(struct folio *folio)
>>>>    {
>>>> -    clear_bit(PG_dcache_clean, &folio->flags);
>>>> +    const unsigned long clear_flags = BIT(PG_dcache_clean) |
>>>> +        BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>>>> +
>>>> +    if (!system_supports_mte()) {
>>>> +        clear_bit(PG_dcache_clean, &folio->flags);
>>>> +        return;
>>>> +    }
>>>> +
>>>> +    folio->flags &= ~clear_flags;
>>>>    }
>>>>    #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>>>>    diff --git a/arch/arm64/include/asm/mman.h
>>>> b/arch/arm64/include/asm/mman.h
>>>> index 5966ee4a6154..304dfc499e68 100644
>>>> --- a/arch/arm64/include/asm/mman.h
>>>> +++ b/arch/arm64/include/asm/mman.h
>>>> @@ -28,7 +28,8 @@ static inline unsigned long
>>>> arch_calc_vm_flag_bits(unsigned long flags)
>>>>         * backed by tags-capable memory. The vm_flags may be
>>>> overridden by a
>>>>         * filesystem supporting MTE (RAM-based).
>>>>         */
>>>> -    if (system_supports_mte() && (flags & MAP_ANONYMOUS))
>>>> +    if (system_supports_mte() &&
>>>> +        (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>>>>            return VM_MTE_ALLOWED;
>>>>          return 0;
>>>> diff --git a/arch/arm64/kernel/hibernate.c
>>>> b/arch/arm64/kernel/hibernate.c
>>>> index 02870beb271e..722e76f29141 100644
>>>> --- a/arch/arm64/kernel/hibernate.c
>>>> +++ b/arch/arm64/kernel/hibernate.c
>>>> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>>>>            max_zone_pfn = zone_end_pfn(zone);
>>>>            for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; 
>>>> pfn++) {
>>>>                struct page *page = pfn_to_online_page(pfn);
>>>> +            struct folio *folio;
>>>>                  if (!page)
>>>>                    continue;
>>>>    +            folio = page_folio(page);
>>>> +
>>>> +            if (folio_test_hugetlb(folio) &&
>>>> +                !page_mte_tagged(&folio->page))
>>>> +                continue;
>>>
>>> Can we have folio_test_mte_tagged() whereby you make sure that only
>>> folio_test_hugetlb() uses it for now (VM_WARN_ON_ONCE) and then make
>>> sure that nobody uses page_mte_tagged() on hugetlb folios
>>> (VM_WARN_ON_ONCE)?
>>
>>
>> IIUC, you mean something like the below?
>>
>> bool folio_test_mte_tagged(struct folio *folio)
>> {
>>       VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
>>
>>       return test_bit(PG_mte_tagged, &folio->page->flags);
>
> folio->flags
>
>> }
>>
>> bool page_mte_tagged(struct page *page)
>> {
>>       struct folio *folio = page_folio(page);
>>
>>       VM_WARN_ON_ONCE(folio_test_hugetlb(folio));
>
> Yes, but better as
>
> VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));

I see. But I think all the call sites for folio_test_mte_tagged() 
actually need have folio_test_hugetlb() before it. So the warn seems not 
very useful other than warning on some misuse.

>
>>
>>       return test_bit(PG_mte_tagged, &pge->flags);
>> }
>>
>>>
>>> Same for folio_set_mte_tagged() and other functions. We could slap a
>>> "hugetlb" into the function names, but maybe in the future we'll be
>>> able to use a single flag per folio (I know, it's complicated ...).
>>
>> A single flag per folio should be the future direction, but I haven't
>> done the research so can't tell how complicated it will be.
>
> There were some discussions on it, and it's tricky. So maybe we should 
> really just have folio_test_hugetlb_mte_tagged() etc. for now

Either w/ hugetlb or w/o hugetlb is fine, I don't have strong opinion on 
the naming.
David Hildenbrand Sept. 4, 2024, 6:35 p.m. UTC | #8
On 04.09.24 19:57, Yang Shi wrote:
> 
> 
> On 9/3/24 2:35 PM, David Hildenbrand wrote:
>> On 03.09.24 18:46, Yang Shi wrote:
>>>
>>>
>>> On 9/2/24 7:33 AM, David Hildenbrand wrote:
>>>> On 21.08.24 20:47, Yang Shi wrote:
>>>>> Enable MTE support for hugetlb.
>>>>>
>>>>> The MTE page flags will be set on the head page only.  When copying
>>>>> hugetlb folio, the tags for all tail pages will be copied when copying
>>>>> head page.
>>>>>
>>>>> When freeing hugetlb folio, the MTE flags will be cleared.
>>>>>
>>>>> Signed-off-by: Yang Shi <yang@os.amperecomputing.com>
>>>>> ---
>>>>>     arch/arm64/include/asm/hugetlb.h | 11 ++++++++++-
>>>>>     arch/arm64/include/asm/mman.h    |  3 ++-
>>>>>     arch/arm64/kernel/hibernate.c    |  7 +++++++
>>>>>     arch/arm64/kernel/mte.c          | 25 +++++++++++++++++++++++--
>>>>>     arch/arm64/kvm/guest.c           | 16 +++++++++++++---
>>>>>     arch/arm64/kvm/mmu.c             | 11 +++++++++++
>>>>>     arch/arm64/mm/copypage.c         | 25 +++++++++++++++++++++++--
>>>>>     fs/hugetlbfs/inode.c             |  2 +-
>>>>>     8 files changed, 90 insertions(+), 10 deletions(-)
>>>>>
>>>>> v2: * Reimplemented the patch to fix the comments from Catalin.
>>>>>        * Added test cases (patch #2) per Catalin.
>>>>>
>>>>> diff --git a/arch/arm64/include/asm/hugetlb.h
>>>>> b/arch/arm64/include/asm/hugetlb.h
>>>>> index 293f880865e8..00a1f75d40ee 100644
>>>>> --- a/arch/arm64/include/asm/hugetlb.h
>>>>> +++ b/arch/arm64/include/asm/hugetlb.h
>>>>> @@ -11,6 +11,7 @@
>>>>>     #define __ASM_HUGETLB_H
>>>>>       #include <asm/cacheflush.h>
>>>>> +#include <asm/mte.h>
>>>>>     #include <asm/page.h>
>>>>>       #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
>>>>> @@ -20,7 +21,15 @@ extern bool
>>>>> arch_hugetlb_migration_supported(struct hstate *h);
>>>>>       static inline void arch_clear_hugetlb_flags(struct folio *folio)
>>>>>     {
>>>>> -    clear_bit(PG_dcache_clean, &folio->flags);
>>>>> +    const unsigned long clear_flags = BIT(PG_dcache_clean) |
>>>>> +        BIT(PG_mte_tagged) | BIT(PG_mte_lock);
>>>>> +
>>>>> +    if (!system_supports_mte()) {
>>>>> +        clear_bit(PG_dcache_clean, &folio->flags);
>>>>> +        return;
>>>>> +    }
>>>>> +
>>>>> +    folio->flags &= ~clear_flags;
>>>>>     }
>>>>>     #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
>>>>>     diff --git a/arch/arm64/include/asm/mman.h
>>>>> b/arch/arm64/include/asm/mman.h
>>>>> index 5966ee4a6154..304dfc499e68 100644
>>>>> --- a/arch/arm64/include/asm/mman.h
>>>>> +++ b/arch/arm64/include/asm/mman.h
>>>>> @@ -28,7 +28,8 @@ static inline unsigned long
>>>>> arch_calc_vm_flag_bits(unsigned long flags)
>>>>>          * backed by tags-capable memory. The vm_flags may be
>>>>> overridden by a
>>>>>          * filesystem supporting MTE (RAM-based).
>>>>>          */
>>>>> -    if (system_supports_mte() && (flags & MAP_ANONYMOUS))
>>>>> +    if (system_supports_mte() &&
>>>>> +        (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
>>>>>             return VM_MTE_ALLOWED;
>>>>>           return 0;
>>>>> diff --git a/arch/arm64/kernel/hibernate.c
>>>>> b/arch/arm64/kernel/hibernate.c
>>>>> index 02870beb271e..722e76f29141 100644
>>>>> --- a/arch/arm64/kernel/hibernate.c
>>>>> +++ b/arch/arm64/kernel/hibernate.c
>>>>> @@ -266,10 +266,17 @@ static int swsusp_mte_save_tags(void)
>>>>>             max_zone_pfn = zone_end_pfn(zone);
>>>>>             for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn;
>>>>> pfn++) {
>>>>>                 struct page *page = pfn_to_online_page(pfn);
>>>>> +            struct folio *folio;
>>>>>                   if (!page)
>>>>>                     continue;
>>>>>     +            folio = page_folio(page);
>>>>> +
>>>>> +            if (folio_test_hugetlb(folio) &&
>>>>> +                !page_mte_tagged(&folio->page))
>>>>> +                continue;
>>>>
>>>> Can we have folio_test_mte_tagged() whereby you make sure that only
>>>> folio_test_hugetlb() uses it for now (VM_WARN_ON_ONCE) and then make
>>>> sure that nobody uses page_mte_tagged() on hugetlb folios
>>>> (VM_WARN_ON_ONCE)?
>>>
>>>
>>> IIUC, you mean something like the below?
>>>
>>> bool folio_test_mte_tagged(struct folio *folio)
>>> {
>>>        VM_WARN_ON_ONCE(!folio_test_hugetlb(folio));
>>>
>>>        return test_bit(PG_mte_tagged, &folio->page->flags);
>>
>> folio->flags
>>
>>> }
>>>
>>> bool page_mte_tagged(struct page *page)
>>> {
>>>        struct folio *folio = page_folio(page);
>>>
>>>        VM_WARN_ON_ONCE(folio_test_hugetlb(folio));
>>
>> Yes, but better as
>>
>> VM_WARN_ON_ONCE(folio_test_hugetlb(page_folio(page)));
> 
> I see. But I think all the call sites for folio_test_mte_tagged()
> actually need have folio_test_hugetlb() before it. So the warn seems not
> very useful other than warning on some misuse.

... well, that's the whole reason for them :)

> 
>>
>>>
>>>        return test_bit(PG_mte_tagged, &pge->flags);
>>> }
>>>
>>>>
>>>> Same for folio_set_mte_tagged() and other functions. We could slap a
>>>> "hugetlb" into the function names, but maybe in the future we'll be
>>>> able to use a single flag per folio (I know, it's complicated ...).
>>>
>>> A single flag per folio should be the future direction, but I haven't
>>> done the research so can't tell how complicated it will be.
>>
>> There were some discussions on it, and it's tricky. So maybe we should
>> really just have folio_test_hugetlb_mte_tagged() etc. for now
> 
> Either w/ hugetlb or w/o hugetlb is fine, I don't have strong opinion on
> the naming.

Let's go with "hugetlb" for now, using it for other large folios is out 
of sight a bit ... at least right now :)
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/hugetlb.h b/arch/arm64/include/asm/hugetlb.h
index 293f880865e8..00a1f75d40ee 100644
--- a/arch/arm64/include/asm/hugetlb.h
+++ b/arch/arm64/include/asm/hugetlb.h
@@ -11,6 +11,7 @@ 
 #define __ASM_HUGETLB_H
 
 #include <asm/cacheflush.h>
+#include <asm/mte.h>
 #include <asm/page.h>
 
 #ifdef CONFIG_ARCH_ENABLE_HUGEPAGE_MIGRATION
@@ -20,7 +21,15 @@  extern bool arch_hugetlb_migration_supported(struct hstate *h);
 
 static inline void arch_clear_hugetlb_flags(struct folio *folio)
 {
-	clear_bit(PG_dcache_clean, &folio->flags);
+	const unsigned long clear_flags = BIT(PG_dcache_clean) |
+		BIT(PG_mte_tagged) | BIT(PG_mte_lock);
+
+	if (!system_supports_mte()) {
+		clear_bit(PG_dcache_clean, &folio->flags);
+		return;
+	}
+
+	folio->flags &= ~clear_flags;
 }
 #define arch_clear_hugetlb_flags arch_clear_hugetlb_flags
 
diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
index 5966ee4a6154..304dfc499e68 100644
--- a/arch/arm64/include/asm/mman.h
+++ b/arch/arm64/include/asm/mman.h
@@ -28,7 +28,8 @@  static inline unsigned long arch_calc_vm_flag_bits(unsigned long flags)
 	 * backed by tags-capable memory. The vm_flags may be overridden by a
 	 * filesystem supporting MTE (RAM-based).
 	 */
-	if (system_supports_mte() && (flags & MAP_ANONYMOUS))
+	if (system_supports_mte() &&
+	    (flags & (MAP_ANONYMOUS | MAP_HUGETLB)))
 		return VM_MTE_ALLOWED;
 
 	return 0;
diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c
index 02870beb271e..722e76f29141 100644
--- a/arch/arm64/kernel/hibernate.c
+++ b/arch/arm64/kernel/hibernate.c
@@ -266,10 +266,17 @@  static int swsusp_mte_save_tags(void)
 		max_zone_pfn = zone_end_pfn(zone);
 		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
 			struct page *page = pfn_to_online_page(pfn);
+			struct folio *folio;
 
 			if (!page)
 				continue;
 
+			folio = page_folio(page);
+
+			if (folio_test_hugetlb(folio) &&
+			    !page_mte_tagged(&folio->page))
+				continue;
+
 			if (!page_mte_tagged(page))
 				continue;
 
diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index 6174671be7c1..b21f706018f7 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -38,7 +38,22 @@  EXPORT_SYMBOL_GPL(mte_async_or_asymm_mode);
 void mte_sync_tags(pte_t pte, unsigned int nr_pages)
 {
 	struct page *page = pte_page(pte);
-	unsigned int i;
+	struct folio *folio = page_folio(page);
+	unsigned long i;
+
+	if (folio_test_hugetlb(folio)) {
+		unsigned long nr = folio_nr_pages(folio);
+		/* Hugetlb MTE flags are set for head page only */
+		if (try_page_mte_tagging(&folio->page)) {
+			for (i = 0; i < nr; i++, page++)
+				mte_clear_page_tags(page_address(page));
+			set_page_mte_tagged(&folio->page);
+		}
+
+		smp_wmb();
+
+		return;
+	}
 
 	/* if PG_mte_tagged is set, tags have already been initialised */
 	for (i = 0; i < nr_pages; i++, page++) {
@@ -410,6 +425,7 @@  static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 		void *maddr;
 		struct page *page = get_user_page_vma_remote(mm, addr,
 							     gup_flags, &vma);
+		struct folio *folio;
 
 		if (IS_ERR(page)) {
 			err = PTR_ERR(page);
@@ -428,7 +444,12 @@  static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 			put_page(page);
 			break;
 		}
-		WARN_ON_ONCE(!page_mte_tagged(page));
+
+		folio = page_folio(page);
+		if (folio_test_hugetlb(folio))
+			WARN_ON_ONCE(!page_mte_tagged(&folio->page));
+		else
+			WARN_ON_ONCE(!page_mte_tagged(page));
 
 		/* limit access to the end of the page */
 		offset = offset_in_page(addr);
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 11098eb7eb44..77e181d96e97 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -1050,6 +1050,7 @@  int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
 		void *maddr;
 		unsigned long num_tags;
 		struct page *page;
+		struct folio *folio;
 
 		if (is_error_noslot_pfn(pfn)) {
 			ret = -EFAULT;
@@ -1062,10 +1063,13 @@  int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
 			ret = -EFAULT;
 			goto out;
 		}
+		folio = page_folio(page);
 		maddr = page_address(page);
 
 		if (!write) {
-			if (page_mte_tagged(page))
+			if (page_mte_tagged(page) ||
+			    (folio_test_hugetlb(folio) &&
+			     page_mte_tagged(&folio->page)))
 				num_tags = mte_copy_tags_to_user(tags, maddr,
 							MTE_GRANULES_PER_PAGE);
 			else
@@ -1079,14 +1083,20 @@  int kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,
 			 * __set_ptes() in the VMM but still overriding the
 			 * tags, hence ignoring the return value.
 			 */
-			try_page_mte_tagging(page);
+			if (folio_test_hugetlb(folio))
+				try_page_mte_tagging(&folio->page);
+			else
+				try_page_mte_tagging(page);
 			num_tags = mte_copy_tags_from_user(maddr, tags,
 							MTE_GRANULES_PER_PAGE);
 
 			/* uaccess failed, don't leave stale tags */
 			if (num_tags != MTE_GRANULES_PER_PAGE)
 				mte_clear_page_tags(maddr);
-			set_page_mte_tagged(page);
+			if (folio_test_hugetlb(folio))
+				set_page_mte_tagged(&folio->page);
+			else
+				set_page_mte_tagged(page);
 
 			kvm_release_pfn_dirty(pfn);
 		}
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 6981b1bc0946..1fa51ac4e3f4 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1401,10 +1401,21 @@  static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,
 {
 	unsigned long i, nr_pages = size >> PAGE_SHIFT;
 	struct page *page = pfn_to_page(pfn);
+	struct folio *folio = page_folio(page);
 
 	if (!kvm_has_mte(kvm))
 		return;
 
+	if (folio_test_hugetlb(folio)) {
+		/* Hugetlb has MTE flags set on head page only */
+		if (try_page_mte_tagging(&folio->page)) {
+			for (i = 0; i < nr_pages; i++, page++)
+				mte_clear_page_tags(page_address(page));
+			set_page_mte_tagged(&folio->page);
+		}
+		return;
+	}
+
 	for (i = 0; i < nr_pages; i++, page++) {
 		if (try_page_mte_tagging(page)) {
 			mte_clear_page_tags(page_address(page));
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index a7bb20055ce0..0f3b07d4a5cf 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -18,6 +18,9 @@  void copy_highpage(struct page *to, struct page *from)
 {
 	void *kto = page_address(to);
 	void *kfrom = page_address(from);
+	struct folio *src = page_folio(from);
+	struct folio *dst = page_folio(to);
+	unsigned int i, nr_pages;
 
 	copy_page(kto, kfrom);
 
@@ -27,8 +30,26 @@  void copy_highpage(struct page *to, struct page *from)
 	if (system_supports_mte() && page_mte_tagged(from)) {
 		/* It's a new page, shouldn't have been tagged yet */
 		WARN_ON_ONCE(!try_page_mte_tagging(to));
-		mte_copy_page_tags(kto, kfrom);
-		set_page_mte_tagged(to);
+
+		/* Populate tags for all subpages if hugetlb */
+		if (folio_test_hugetlb(src)) {
+			/*
+			 * MTE page flag is just set on the head page of
+			 * hugetlb. If from has MTE flag set, it must be the
+			 * head page.
+			 */
+			VM_BUG_ON(!PageHead(from));
+			nr_pages = folio_nr_pages(src);
+			for (i = 0; i < nr_pages; i++, to++, from++) {
+				kto = page_address(to);
+				kfrom = page_address(from);
+				mte_copy_page_tags(kto, kfrom);
+			}
+			set_page_mte_tagged(&dst->page);
+		} else {
+			mte_copy_page_tags(kto, kfrom);
+			set_page_mte_tagged(to);
+		}
 	}
 }
 EXPORT_SYMBOL(copy_highpage);
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 9f6cff356796..f944e8e7126b 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -110,7 +110,7 @@  static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
 	 * way when do_mmap unwinds (may be important on powerpc
 	 * and ia64).
 	 */
-	vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND);
+	vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND | VM_MTE_ALLOWED);
 	vma->vm_ops = &hugetlb_vm_ops;
 
 	ret = seal_check_write(info->seals, vma);