KVM: arm64: permit MAP_SHARED mappings with MTE enabled
Subsystems (9)
v2 cover KVM: arm64: permit MAP_SHARED mappings with MTE enabled
Hi,
This patch series allows VMMs to use shared mappings in MTE enabled guests. The first four patches are based on the series that Catalin sent out, whose cover letter [1] I quote from below:
Quoted 14 lines
This series aims to fix the races between initialising the tags on a page and setting the
PG_mte_taggedflag. Currently the flag is set either before or after that tag initialisation and this can lead to CoW copying stale tags. The first patch moves the flag setting after the tags have been initialised, solving the CoW issue. However, concurrentmprotect()on a shared mapping may (very rarely) lead to valid tags being zeroed.The second skips the
sanitise_mte_tags()call inkvm_set_spte_gfn(), deferring it touser_mem_abort(). The outcome is that nosanitise_mte_tags()can be simplified to skip thepfn_to_online_page()check and only rely onVM_MTE_ALLOWEDvma flag that can be checked inuser_mem_abort().
Quoted 7 lines
The third and fourth patches use
PG_arch_3as a lock for page tagging, based on Peter Collingbourne's idea of a two-bit lock.I think the first patch can be queued but the rest needs some in depth review and test. With this series (if correct) we could allos
MAP_SHAREDon KVM guest memory but this is to be discussed separately as there are some KVM ABI implications.
I rebased Catalin's series onto -next, addressed the issues that I identified in the review and added the proposed userspace enablement patches after the series.
[1] https://lore.kernel.org/all/[email protected]/
Catalin Marinas (3):
arm64: mte: Fix/clarify the PG_mte_tagged semantics
KVM: arm64: Simplify the sanitise_mte_tags() logic
arm64: mte: Lock a page for MTE tag initialisation
Peter Collingbourne (4):
mm: Add PG_arch_3 page flag
KVM: arm64: unify the tests for VMAs in memslots when MTE is enabled
KVM: arm64: permit all VM_MTE_ALLOWED mappings with MTE enabled
Documentation: document the ABI changes for KVM_CAP_ARM_MTE
Documentation/virt/kvm/api.rst | 5 +-- arch/arm64/include/asm/mte.h | 62 ++++++++++++++++++++++++++++++++ arch/arm64/include/asm/pgtable.h | 3 +- arch/arm64/kernel/cpufeature.c | 4 ++- arch/arm64/kernel/elfcore.c | 2 +- arch/arm64/kernel/hibernate.c | 2 +- arch/arm64/kernel/mte.c | 17 +++++---- arch/arm64/kvm/guest.c | 18 ++++++---- arch/arm64/kvm/mmu.c | 55 ++++++++++++---------------- arch/arm64/mm/copypage.c | 6 ++-- arch/arm64/mm/fault.c | 4 ++- arch/arm64/mm/mteswap.c | 5 ++- fs/proc/page.c | 1 + include/linux/page-flags.h | 1 + include/trace/events/mmflags.h | 7 ++-- mm/huge_memory.c | 1 + 16 files changed, 134 insertions(+), 59 deletions(-)
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
PATCH v2 1/7 arm64: mte: Fix/clarify the PG_mte_tagged semantics
From: Catalin Marinas <[email protected]>
Currently the PG_mte_tagged page flag mostly means the page contains valid tags and it should be set after the tags have been cleared or restored. However, in mte_sync_tags() it is set before setting the tags to avoid, in theory, a race with concurrent mprotect(PROT_MTE) for shared pages. However, a concurrent mprotect(PROT_MTE) with a copy on write in another thread can cause the new page to have stale tags. Similarly, tag reading via ptrace() can read stale tags of the PG_mte_tagged flag is set before actually clearing/restoring the tags.
Fix the PG_mte_tagged semantics so that it is only set after the tags have been cleared or restored. This is safe for swap restoring into a MAP_SHARED or CoW page since the core code takes the page lock. Add two functions to test and set the PG_mte_tagged flag with acquire and release semantics. The downside is that concurrent mprotect(PROT_MTE) on a MAP_SHARED page may cause tag loss. This is already the case for KVM guests if a VMM changes the page protection while the guest triggers a user_mem_abort().
--- arch/arm64/include/asm/mte.h | 30 ++++++++++++++++++++++++++++++ arch/arm64/include/asm/pgtable.h | 2 +- arch/arm64/kernel/cpufeature.c | 4 +++- arch/arm64/kernel/elfcore.c | 2 +- arch/arm64/kernel/hibernate.c | 2 +- arch/arm64/kernel/mte.c | 12 +++++++----- arch/arm64/kvm/guest.c | 4 ++-- arch/arm64/kvm/mmu.c | 4 ++-- arch/arm64/mm/copypage.c | 4 ++-- arch/arm64/mm/fault.c | 2 +- arch/arm64/mm/mteswap.c | 2 +- 11 files changed, 51 insertions(+), 17 deletions(-)
arch/arm64/include/asm/mte.h +30 -0
@@ -37,6 +37,29 @@ void mte_free_tag_storage(char *storage);/* track which pages have valid allocation tags */ #define PG_mte_tagged PG_arch_2 +static inline void set_page_mte_tagged (struct page *page) +{ +/* +* Ensure that the tags written prior to this function are visible +* before the page flags update. +*/ +smp_wmb (); +set_bit (PG_mte_tagged, &page->flags); +} + +static inline bool page_mte_tagged (struct page *page) +{ +bool ret =test_bit (PG_mte_tagged, &page->flags); + +/* +* If the page is tagged, ensure ordering with a likely subsequent +* read of the tags. +*/ +if (ret) +smp_rmb (); +return ret; +} +void mte_zero_clear_page_tags (void *addr);void mte_sync_tags (pte_t old_pte,pte_t pte);void mte_copy_page_tags (void *kto,const void *kfrom);
@@ -54,6 +77,13 @@ size_t mte_probe_user_range(const char __user *uaddr, size_t size);/* unused if !CONFIG_ARM64_MTE, silence the compiler */ #define PG_mte_tagged 0 +static inline set_page_mte_tagged(struct page *page) +{ +} +static inline bool page_mte_tagged (struct page *page) +{ +return false; +}static inline void mte_zero_clear_page_tags (void *addr) { }
arch/arm64/include/asm/pgtable.h +1 -1
@@ -1050,7 +1050,7 @@ static inline void arch_swap_invalidate_area(int type)static inline void arch_swap_restore (swp_entry_t entry,struct folio *folio) {if (system_supports_mte () &&mte_restore_tags (entry, &folio->page)) -set_bit (PG_mte_tagged, &folio->flags); +set_page_mte_tagged (&folio->page); }#endif /* CONFIG_ARM64_MTE */
arch/arm64/kernel/cpufeature.c +3 -1
@@ -2020,8 +2020,10 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)* Clear the tags in the zero page. This needs to be done via the * linear map which has the Tagged attribute. */ -if (!test_and_set_bit (PG_mte_tagged, &ZERO_PAGE (0 )->flags)) +if (!page_mte_tagged (ZERO_PAGE (0 ))) {mte_clear_page_tags (lm_alias (empty_zero_page)); +set_page_mte_tagged (ZERO_PAGE (0 )); + }kasan_init_hw_tags_cpu (); }
arch/arm64/kernel/elfcore.c +1 -1
@@ -47,7 +47,7 @@ static int mte_dump_tag_range(struct coredump_params *cprm,* Pages mapped in user space as !pte_access_permitted() (e.g. * PROT_EXEC only) may not have the PG_mte_tagged flag set. */ -if (!test_bit (PG_mte_tagged, &page->flags)) { +if (!page_mte_tagged (page)) {put_page (page);dump_skip (cprm,MTE_PAGE_TAG_STORAGE );continue ;
arch/arm64/kernel/hibernate.c +1 -1
@@ -271,7 +271,7 @@ static int swsusp_mte_save_tags(void)if (!page)continue ; -if (!test_bit (PG_mte_tagged, &page->flags)) +if (!page_mte_tagged (page))continue ; ret =save_tags (page, pfn);
arch/arm64/kernel/mte.c +7 -5
@@ -41,14 +41,17 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,if (check_swap &&is_swap_pte (old_pte)) {swp_entry_t entry =pte_to_swp_entry (old_pte); -if (!non_swap_entry (entry) &&mte_restore_tags (entry, page)) +if (!non_swap_entry (entry) &&mte_restore_tags (entry, page)) { +set_page_mte_tagged (page);return ; + } }if (!pte_is_tagged)return ;mte_clear_page_tags (page_address (page)); +set_page_mte_tagged (page); }void mte_sync_tags (pte_t old_pte,pte_t pte)
@@ -64,7 +67,7 @@ void mte_sync_tags(pte_t old_pte, pte_t pte)/* if PG_mte_tagged is set, tags have already been initialised */ for (i =0 ; i < nr_pages; i++, page++) { -if (!test_and_set_bit (PG_mte_tagged, &page->flags)) +if (!page_mte_tagged (page))mte_sync_page_tags (page, old_pte, check_swap, pte_is_tagged); }
@@ -91,8 +94,7 @@ int memcmp_pages(struct page *page1, struct page *page2)* pages is tagged, set_pte_at() may zero or change the tags of the * other page via mte_sync_tags(). */ -if (test_bit (PG_mte_tagged, &page1->flags) || -test_bit (PG_mte_tagged, &page2->flags)) +if (page_mte_tagged (page1) ||page_mte_tagged (page2))return addr1 != addr2;return ret;
@@ -398,7 +400,7 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,put_page (page);break ; } -WARN_ON_ONCE (!test_bit (PG_mte_tagged, &page->flags)); +WARN_ON_ONCE (!page_mte_tagged (page));/* limit access to the end of the page */ offset =offset_in_page (addr);
arch/arm64/kvm/guest.c +2 -2
@@ -1058,7 +1058,7 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm, maddr =page_address (page);if (!write) { -if (test_bit (PG_mte_tagged, &page->flags)) +if (page_mte_tagged (page)) num_tags =mte_copy_tags_to_user (tags, maddr,MTE_GRANULES_PER_PAGE );else
@@ -1075,7 +1075,7 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,* completed fully */ if (num_tags ==MTE_GRANULES_PER_PAGE ) -set_bit (PG_mte_tagged, &page->flags); +set_page_mte_tagged (page);kvm_release_pfn_dirty (pfn); }
arch/arm64/kvm/mmu.c +2 -2
@@ -1075,9 +1075,9 @@ static int sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,return -EFAULT ;for (i =0 ; i < nr_pages; i++, page++) { -if (!test_bit (PG_mte_tagged, &page->flags)) { +if (!page_mte_tagged (page)) {mte_clear_page_tags (page_address (page)); -set_bit (PG_mte_tagged, &page->flags); +set_page_mte_tagged (page); } }
arch/arm64/mm/copypage.c +2 -2
@@ -21,9 +21,9 @@ void copy_highpage(struct page *to, struct page *from)copy_page (kto, kfrom); -if (system_supports_mte () &&test_bit (PG_mte_tagged, &from->flags)) { -set_bit (PG_mte_tagged, &to->flags); +if (system_supports_mte () &&page_mte_tagged (from)) {mte_copy_page_tags (kto, kfrom); +set_page_mte_tagged (to); } }EXPORT_SYMBOL (copy_highpage);
arch/arm64/mm/fault.c +1 -1
@@ -931,5 +931,5 @@ struct page *alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,void tag_clear_highpage (struct page *page) {mte_zero_clear_page_tags (page_address (page)); -set_bit (PG_mte_tagged, &page->flags); +set_page_mte_tagged (page); }
arch/arm64/mm/mteswap.c +1 -1
@@ -24,7 +24,7 @@ int mte_save_tags(struct page *page) {void *tag_storage, *ret; -if (!test_bit (PG_mte_tagged, &page->flags)) +if (!page_mte_tagged (page))return 0 ; tag_storage =mte_allocate_tag_storage ();
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
kernel test robot
build botRe: [PATCH v2 1/7] arm64: mte: Fix/clarify the PG_mte_tagged semantics
I love your patch! Yet something to improve:
Hi Peter,
I love your patch! Yet something to improve:
[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on next-20220722]
[cannot apply to kvmarm/next arm/for-next soc/for-next xilinx-xlnx/master linus/master v5.19-rc7] [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/Peter-Collingbourne/KVM-arm64-permit-MAP_SHARED-mappings-with-MTE-enabled/20220722-095300 base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core config: arm64-randconfig-s032-20220721 (https://download.01.org/0day-ci/archive/20220723/[email protected]/config) compiler: aarch64-linux-gcc (GCC) 12.1.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# apt-get install sparse
# sparse version: v0.6.4-39-gce1a6720-dirty
# https://github.com/intel-lab-lkp/linux/commit/3323e416892d6b5326503b9afc2ee835162b819b
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Peter-Collingbourne/KVM-arm64-permit-MAP_SHARED-mappings-with-MTE-enabled/20220722-095300 git checkout 3323e416892d6b5326503b9afc2ee835162b819b
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' O=build_dir ARCH=arm64 prepare
If you fix the issue, kindly add following tag where applicable
All errors (new ones prefixed by >>):
In file included from arch/arm64/include/asm/pgtable.h:12,
from include/linux/pgtable.h:6,
from include/linux/kasan.h:33,
from include/linux/slab.h:140,
from include/linux/resource_ext.h:11,
from include/linux/acpi.h:14,
from include/acpi/apei.h:9,
from include/acpi/ghes.h:5,
from include/linux/arm_sdei.h:8,
from arch/arm64/kernel/asm-offsets.c:10:
>> arch/arm64/include/asm/mte.h:80:15: error: return type defaults to 'int' [-Werror=implicit-int] 80 | static inline set_page_mte_tagged(struct page *page)
| ^~~~~~~~~~~~~~~~~~~
cc1: some warnings being treated as errors
make[2]: *** [scripts/Makefile.build:117: arch/arm64/kernel/asm-offsets.s] Error 1 make[2]: Target '__build' not remade because of errors.
make[1]: *** [Makefile:1200: prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:219: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.
vim +/int +80 arch/arm64/include/asm/mte.h
79
> 80 static inline set_page_mte_tagged(struct page *page)
81 {
82 }
83 static inline bool page_mte_tagged(struct page *page)
84 {
85 return false;
86 }
87 static inline void mte_zero_clear_page_tags(void *addr)
88 {
89 }
90 static inline void mte_sync_tags(pte_t old_pte, pte_t pte)
91 {
92 }
93 static inline void mte_copy_page_tags(void *kto, const void *kfrom)
94 {
95 }
96 static inline void mte_thread_init_user(void)
97 {
98 }
99 static inline void mte_thread_switch(struct task_struct *next) 100 {
101 }
102 static inline void mte_suspend_enter(void)
103 {
104 }
105 static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg)
106 {
107 return 0;
108 }
109 static inline long get_mte_ctrl(struct task_struct *task)
110 {
111 return 0;
112 }
113 static inline int mte_ptrace_copy_tags(struct task_struct *child,
114 long request, unsigned long addr,
115 unsigned long data)
116 {
117 return -EIO;
118 }
119
Signature · 6 lines
0-DAY CI Kernel Test Service https://01.org/lkp _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
kernel test robot
build botRe: [PATCH v2 1/7] arm64: mte: Fix/clarify the PG_mte_tagged semantics
In reply to Peter CollingbourneI love your patch! Yet something to improve:
Hi Peter,
I love your patch! Yet something to improve:
[auto build test ERROR on arm64/for-next/core]
[also build test ERROR on next-20220722]
[cannot apply to kvmarm/next arm/for-next soc/for-next xilinx-xlnx/master linus/master v5.19-rc7] [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/Peter-Collingbourne/KVM-arm64-permit-MAP_SHARED-mappings-with-MTE-enabled/20220722-095300 base: https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git for-next/core config: arm64-buildonly-randconfig-r004-20220722 (https://download.01.org/0day-ci/archive/20220724/[email protected]/config) compiler: clang version 15.0.0 (https://github.com/llvm/llvm-project 72686d68c137551cce816416190a18d45b4d4e2a)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross
# install arm64 cross compiling tool for clang build
# apt-get install binutils-aarch64-linux-gnu
# https://github.com/intel-lab-lkp/linux/commit/3323e416892d6b5326503b9afc2ee835162b819b
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Peter-Collingbourne/KVM-arm64-permit-MAP_SHARED-mappings-with-MTE-enabled/20220722-095300 git checkout 3323e416892d6b5326503b9afc2ee835162b819b
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm64 prepare
If you fix the issue, kindly add following tag where applicable
All errors (new ones prefixed by >>):
In file included from arch/arm64/kernel/asm-offsets.c:10:
In file included from include/linux/arm_sdei.h:8:
In file included from include/acpi/ghes.h:5:
In file included from include/acpi/apei.h:9:
In file included from include/linux/acpi.h:15:
In file included from include/linux/device.h:32:
In file included from include/linux/device/driver.h:21:
In file included from include/linux/module.h:19:
In file included from include/linux/elf.h:6:
In file included from arch/arm64/include/asm/elf.h:141:
In file included from include/linux/fs.h:33:
In file included from include/linux/percpu-rwsem.h:7:
In file included from include/linux/rcuwait.h:6:
In file included from include/linux/sched/signal.h:9:
In file included from include/linux/sched/task.h:11:
In file included from include/linux/uaccess.h:11:
In file included from arch/arm64/include/asm/uaccess.h:24:
>> arch/arm64/include/asm/mte.h:80:15: error: type specifier missing, defaults to 'int'; ISO C99 and later do not support implicit int [-Wimplicit-int]
static inline set_page_mte_tagged(struct page *page)
~~~~~~~~~~~~~ ^
int
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:456:22: warning: array index 3 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:456:10: warning: array index 7 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:456:42: warning: array index 6 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:456:53: warning: array index 3 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:458:22: warning: array index 2 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:458:10: warning: array index 5 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:458:42: warning: array index 4 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:458:53: warning: array index 2 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:460:22: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^
In file included from arch/arm64/kernel/asm-offsets.c:12:
In file included from include/linux/kexec.h:31:
include/linux/compat.h:460:10: warning: array index 3 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:460:42: warning: array index 2 is past the end of the array (which contains 2 elements) [-Warray-bounds]
case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1];
^ ~
include/linux/compat.h:131:2: note: array 'sig' declared here
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
^
include/linux/compat.h:460:53: warning: array index 1 is past the end of the array (which contains 1 element) [-Warray-bounds]
case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1];
^ ~
include/uapi/asm-generic/signal.h:62:2: note: array 'sig' declared here
unsigned long sig[_NSIG_WORDS];
^ 12 warnings and 1 error generated.
make[2]: *** [scripts/Makefile.build:117: arch/arm64/kernel/asm-offsets.s] Error 1 make[2]: Target '__build' not remade because of errors.
make[1]: *** [Makefile:1200: prepare0] Error 2
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:219: __sub-make] Error 2
make: Target 'prepare' not remade because of errors.
vim +/int +80 arch/arm64/include/asm/mte.h
79
> 80 static inline set_page_mte_tagged(struct page *page)
81 {
82 }
83 static inline bool page_mte_tagged(struct page *page)
84 {
85 return false;
86 }
87 static inline void mte_zero_clear_page_tags(void *addr)
88 {
89 }
90 static inline void mte_sync_tags(pte_t old_pte, pte_t pte)
91 {
92 }
93 static inline void mte_copy_page_tags(void *kto, const void *kfrom)
94 {
95 }
96 static inline void mte_thread_init_user(void)
97 {
98 }
99 static inline void mte_thread_switch(struct task_struct *next) 100 {
101 }
102 static inline void mte_suspend_enter(void)
103 {
104 }
105 static inline long set_mte_ctrl(struct task_struct *task, unsigned long arg)
106 {
107 return 0;
108 }
109 static inline long get_mte_ctrl(struct task_struct *task)
110 {
111 return 0;
112 }
113 static inline int mte_ptrace_copy_tags(struct task_struct *child,
114 long request, unsigned long addr,
115 unsigned long data)
116 {
117 return -EIO;
118 }
119
Signature · 2 lines
0-DAY CI Kernel Test Service https://01.org/lkp
PATCH v2 2/7 KVM: arm64: Simplify the sanitise_mte_tags() logic
In reply to Peter CollingbourneFrom: Catalin Marinas <[email protected]>
Currently sanitise_mte_tags() checks if it's an online page before attempting to sanitise the tags. Such detection should be done in the caller via the VM_MTE_ALLOWED vma flag. Since kvm_set_spte_gfn() does not have the vma, leave the page unmapped if not already tagged. Tag initialisation will be done on a subsequent access fault in user_mem_abort().
--- arch/arm64/kvm/mmu.c | 40 +++++++++++++++------------------------- 1 file changed, 15 insertions(+), 25 deletions(-)
arch/arm64/kvm/mmu.c +15 -25
@@ -1056,23 +1056,14 @@ static int get_vma_page_shift(struct vm_area_struct *vma, unsigned long hva)* - mmap_lock protects between a VM faulting a page in and the VMM performing * an mprotect() to add VM_MTE */ -static int sanitise_mte_tags (struct kvm *kvm,kvm_pfn_t pfn, -unsigned long size) +static void sanitise_mte_tags (struct kvm *kvm,kvm_pfn_t pfn, +unsigned long size) {unsigned long i, nr_pages = size >>PAGE_SHIFT ; -struct page *page; +struct page *page =pfn_to_page (pfn);if (!kvm_has_mte (kvm)) -return 0 ; - -/* -* pfn_to_online_page() is used to reject ZONE_DEVICE pages -* that may not support tags. -*/ - page =pfn_to_online_page (pfn); - -if (!page) -return -EFAULT ; +return ;for (i =0 ; i < nr_pages; i++, page++) {if (!page_mte_tagged (page)) {
@@ -1080,8 +1071,6 @@ static int sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,set_page_mte_tagged (page); } } - -return 0 ; } static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
@@ -1092,7 +1081,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,bool write_fault, writable, force_pte = false;bool exec_fault;bool device = false; -bool shared;unsigned long mmu_seq;struct kvm *kvm = vcpu->kvm;struct kvm_mmu_memory_cache *memcache = &vcpu->arch.mmu_page_cache;
@@ -1142,8 +1130,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, vma_shift =get_vma_page_shift (vma, hva); } - shared = (vma->vm_flags &VM_SHARED ); -switch (vma_shift) {#ifndef __PAGETABLE_PMD_FOLDEDcase PUD_SHIFT :
@@ -1264,12 +1250,13 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,if (fault_status !=FSC_PERM && !device &&kvm_has_mte (kvm)) {/* Check the VMM hasn't introduced a new VM_SHARED VMA */ -if (!shared) - ret =sanitise_mte_tags (kvm, pfn, vma_pagesize); -else +if ((vma->vm_flags &VM_MTE_ALLOWED ) && + !(vma->vm_flags &VM_SHARED )) { +sanitise_mte_tags (kvm, pfn, vma_pagesize); + }else { ret = -EFAULT ; -if (ret) goto out_unlock; + } }if (writable)
@@ -1491,15 +1478,18 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)bool kvm_set_spte_gfn (struct kvm *kvm,struct kvm_gfn_range *range) {kvm_pfn_t pfn =pte_pfn (range->pte); -int ret;if (!kvm->arch.mmu.pgt)return false;WARN_ON (range->end - range->start !=1 ); - ret =sanitise_mte_tags (kvm, pfn,PAGE_SIZE ); -if (ret) +/* +* If the page isn't tagged, defer to user_mem_abort() for sanitising +* the MTE tags. The S2 pte should have been unmapped by +* mmu_notifier_invalidate_range_end(). +*/ +if (kvm_has_mte (kvm) && !page_mte_tagged (pfn_to_page (pfn)))return false;/*
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
PATCH v2 3/7 mm: Add PG_arch_3 page flag
In reply to Peter CollingbourneAs with PG_arch_2, this flag is only allowed on 64-bit architectures due to the shortage of bits available. It will be used by the arm64 MTE code in subsequent patches.
--- fs/proc/page.c | 1 + include/linux/page-flags.h | 1 + include/trace/events/mmflags.h | 7 ++++--- mm/huge_memory.c | 1 + 4 files changed, 7 insertions(+), 3 deletions(-)
fs/proc/page.c +1 -0
@@ -220,6 +220,7 @@ u64 stable_page_flags(struct page *page) u |=kpf_copy_bit (k,KPF_ARCH , PG_arch_1);#ifdef CONFIG_64BIT u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_2); + u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_3);#endif return u;
include/linux/page-flags.h +1 -0
@@ -134,6 +134,7 @@ enum pageflags {#endif #ifdef CONFIG_64BIT PG_arch_2, + PG_arch_3,#endif #ifdef CONFIG_KASAN_HW_TAGS PG_skip_kasan_poison,
include/trace/events/mmflags.h +4 -3
@@ -91,9 +91,9 @@#endif #ifdef CONFIG_64BIT -#define IF_HAVE_PG_ARCH_2 (flag,string) ,{1UL << flag, string} +#define IF_HAVE_PG_ARCH_2_3 (flag,string) ,{1UL << flag, string}#else -#define IF_HAVE_PG_ARCH_2 (flag,string) +#define IF_HAVE_PG_ARCH_2_3 (flag,string)#endif #ifdef CONFIG_KASAN_HW_TAGS
@@ -129,7 +129,8 @@ IF_HAVE_PG_UNCACHED(PG_uncached, "uncached" ) \ IF_HAVE_PG_HWPOISON(PG_hwpoison, "hwpoison" ) \ IF_HAVE_PG_IDLE(PG_young, "young" ) \ IF_HAVE_PG_IDLE(PG_idle, "idle" ) \ -IF_HAVE_PG_ARCH_2(PG_arch_2, "arch_2" ) \ +IF_HAVE_PG_ARCH_2_3(PG_arch_2, "arch_2" ) \ +IF_HAVE_PG_ARCH_2_3(PG_arch_3, "arch_3" ) \ IF_HAVE_PG_SKIP_KASAN_POISON(PG_skip_kasan_poison, "skip_kasan_poison")#define show_page_flags (flags) \
mm/huge_memory.c +1 -0
@@ -2399,6 +2399,7 @@ static void __split_huge_page_tail(struct page *head, int tail, (1L << PG_unevictable) | #ifdef CONFIG_64BIT (1L << PG_arch_2) | + (1L << PG_arch_3) | #endif (1L << PG_dirty)));
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
Marc Zyngier
maintainerRe: [PATCH v2 3/7] mm: Add PG_arch_3 page flag
Quoted 23 lines · Peter Collingbourne
As with
PG_arch_2, this flag is only allowed on 64-bit architectures due to the shortage of bits available. It will be used by the arm64 MTE code in subsequent patches.Signed-off-by Peter Collingbourne <[email protected]>Cc Will Deacon <[email protected]>Cc Marc Zyngier <[email protected]>Cc Steven Price <[email protected]>[[email protected]: added flag preserving in __split_huge_page_tail()]Signed-off-by Catalin Marinas <[email protected]>--- fs/proc/page.c | 1 + include/linux/page-flags.h | 1 + include/trace/events/mmflags.h | 7 ++++--- mm/huge_memory.c | 1 + 4 files changed, 7 insertions(+), 3 deletions(-)fs/proc/page.c +0
-0
fs/proc/page.c u64 stable_page_flags(struct page *page) · line 223
Quoted 4 lines
fs/proc/page.c +1
-0@@ -220,6 +220,7 @@ u64 stable_page_flags(struct page *page) u |=kpf_copy_bit (k,KPF_ARCH , PG_arch_1);#ifdef CONFIG_64BIT u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_2); + u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_3);
Are PG_arch_2 and PG_arch_3 supposed to share the same user bit in /proc/kpageflags? This seems odd.
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Re: [PATCH v2 3/7] mm: Add PG_arch_3 page flag
Quoted 20 lines · Marc Zyngier
Quoted 18 lines · Peter Collingbourne
As with
PG_arch_2, this flag is only allowed on 64-bit architectures due to the shortage of bits available. It will be used by the arm64 MTE code in subsequent patches.Signed-off-by Peter Collingbourne <[email protected]>Cc Will Deacon <[email protected]>Cc Marc Zyngier <[email protected]>Cc Steven Price <[email protected]>[[email protected]: added flag preserving in __split_huge_page_tail()]Signed-off-by Catalin Marinas <[email protected]>--- fs/proc/page.c | 1 + include/linux/page-flags.h | 1 + include/trace/events/mmflags.h | 7 ++++--- mm/huge_memory.c | 1 + 4 files changed, 7 insertions(+), 3 deletions(-)
Quoted 12 lines
fs/proc/page.c u64 stable_page_flags(struct page *page) · line 223
Quoted 9 lines
fs/proc/page.c +1
-0@@ -220,6 +220,7 @@ u64 stable_page_flags(struct page *page) u |=kpf_copy_bit (k,KPF_ARCH , PG_arch_1);#ifdef CONFIG_64BIT u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_2); + u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_3);Are
PG_arch_2andPG_arch_3supposed to share the same user bit in/proc/kpageflags? This seems odd.
No, that was an oversight, thanks for the catch. I will fix it up like so in v3.
Peter
fs/proc/page.c +1 -1
@@ -220,7 +220,7 @@ u64 stable_page_flags(struct page *page) u |=kpf_copy_bit (k,KPF_ARCH , PG_arch_1);#ifdef CONFIG_64BIT u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_2); - u |=kpf_copy_bit (k,KPF_ARCH_2 , PG_arch_3); + u |=kpf_copy_bit (k,KPF_ARCH_3 , PG_arch_3);#endif return u;
include/linux/kernel-page-flags.h +1 -0
@@ -18,5 +18,6 @@#define KPF_UNCACHED 39#define KPF_SOFTDIRTY 40#define KPF_ARCH_2 41 +#define KPF_ARCH_3 42#endif /* LINUX_KERNEL_PAGE_FLAGS_H */
tools/vm/page-types.c +2 -0
@@ -79,6 +79,7 @@#define KPF_UNCACHED 39#define KPF_SOFTDIRTY 40#define KPF_ARCH_2 41 +#define KPF_ARCH_3 42/* [47-] take some arbitrary free slots for expanding overloaded flags * not part of kernel API
@@ -138,6 +139,7 @@ static const char * const page_flag_names[] = { [KPF_UNCACHED] = "c:uncached", [KPF_SOFTDIRTY] = "f:softdirty", [KPF_ARCH_2] = "H:arch_2", + [KPF_ARCH_3] = "H:arch_3", [KPF_ANON_EXCLUSIVE] = "d:anon_exclusive", [KPF_READAHEAD] = "I:readahead",
PATCH v2 4/7 arm64: mte: Lock a page for MTE tag initialisation
In reply to Peter CollingbourneFrom: Catalin Marinas <[email protected]>
Initialising the tags and setting PG_mte_tagged flag for a page can race between multiple set_pte_at() on shared pages or setting the stage 2 pte via user_mem_abort(). Introduce a new PG_mte_lock flag as PG_arch_3 and set it before attempting page initialisation. Given that PG_mte_tagged is never cleared for a page, consider setting this flag to mean page unlocked and wait on this bit with acquire semantics if the page is locked:
- try_page_mte_tagging() - lock the page for tagging, return true if it can be tagged, false if already tagged. No acquire semantics if it returns true (PG_mte_tagged not set) as there is no serialisation with a previous set_page_mte_tagged().
- set_page_mte_tagged() - set PG_mte_tagged with release semantics.
The two-bit locking is based on Peter Collingbourne's idea.
--- arch/arm64/include/asm/mte.h | 32 ++++++++++++++++++++++++++++++++ arch/arm64/include/asm/pgtable.h | 1 + arch/arm64/kernel/cpufeature.c | 2 +- arch/arm64/kernel/mte.c | 7 +++++-- arch/arm64/kvm/guest.c | 16 ++++++++++------ arch/arm64/kvm/mmu.c | 2 +- arch/arm64/mm/copypage.c | 2 ++ arch/arm64/mm/fault.c | 2 ++ arch/arm64/mm/mteswap.c | 3 +++ 9 files changed, 57 insertions(+), 10 deletions(-)
arch/arm64/include/asm/mte.h +32 -0
@@ -36,6 +36,8 @@ void mte_free_tag_storage(char *storage);/* track which pages have valid allocation tags */ #define PG_mte_tagged PG_arch_2 +/* simple lock to avoid multiple threads tagging the same page */ +#define PG_mte_lock PG_arch_3static inline void set_page_mte_tagged (struct page *page) {
@@ -60,6 +62,32 @@ static inline bool page_mte_tagged(struct page *page)return ret; } +/* +* Lock the page for tagging and return 'true' if the page can be tagged, +* 'false' if already tagged. PG_mte_tagged is never cleared and therefore the +* locking only happens once for page initialisation. +* +* The page MTE lock state: +* +* Locked: PG_mte_lock && !PG_mte_tagged +* Unlocked: !PG_mte_lock || PG_mte_tagged +* +* Acquire semantics only if the page is tagged (returning 'false'). +*/ +static inline bool try_page_mte_tagging (struct page *page) +{ +if (!test_and_set_bit (PG_mte_lock, &page->flags)) +return true; + +/* +* The tags are either being initialised or have already been initialised, +* wait for the PG_mte_tagged flag to be set. +*/ +smp_cond_load_acquire (&page->flags,VAL & (1UL << PG_mte_tagged)); + +return false; +} +void mte_zero_clear_page_tags (void *addr);void mte_sync_tags (pte_t old_pte,pte_t pte);void mte_copy_page_tags (void *kto,const void *kfrom);
@@ -84,6 +112,10 @@ static inline bool page_mte_tagged(struct page *page) {return false; } +static inline bool try_page_mte_tagging (struct page *page) +{ +return false; +}static inline void mte_zero_clear_page_tags (void *addr) { }
arch/arm64/include/asm/pgtable.h +1 -0
@@ -1049,6 +1049,7 @@ static inline void arch_swap_invalidate_area(int type)#define __HAVE_ARCH_SWAP_RESTOREstatic inline void arch_swap_restore (swp_entry_t entry,struct folio *folio) { +/* mte_restore_tags() takes the PG_mte_lock */ if (system_supports_mte () &&mte_restore_tags (entry, &folio->page))set_page_mte_tagged (&folio->page); }
arch/arm64/kernel/cpufeature.c +1 -1
@@ -2020,7 +2020,7 @@ static void cpu_enable_mte(struct arm64_cpu_capabilities const *cap)* Clear the tags in the zero page. This needs to be done via the * linear map which has the Tagged attribute. */ -if (!page_mte_tagged (ZERO_PAGE (0 ))) { +if (try_page_mte_tagging (ZERO_PAGE (0 ))) {mte_clear_page_tags (lm_alias (empty_zero_page));set_page_mte_tagged (ZERO_PAGE (0 )); }
arch/arm64/kernel/mte.c +5 -2
@@ -41,6 +41,7 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,if (check_swap &&is_swap_pte (old_pte)) {swp_entry_t entry =pte_to_swp_entry (old_pte); +/* mte_restore_tags() takes the PG_mte_lock */ if (!non_swap_entry (entry) &&mte_restore_tags (entry, page)) {set_page_mte_tagged (page);return ;
@@ -50,8 +51,10 @@ static void mte_sync_page_tags(struct page *page, pte_t old_pte,if (!pte_is_tagged)return ; -mte_clear_page_tags (page_address (page)); -set_page_mte_tagged (page); +if (try_page_mte_tagging (page)) { +mte_clear_page_tags (page_address (page)); +set_page_mte_tagged (page); + } }void mte_sync_tags (pte_t old_pte,pte_t pte)
arch/arm64/kvm/guest.c +10 -6
@@ -1067,15 +1067,19 @@ long kvm_vm_ioctl_mte_copy_tags(struct kvm *kvm,clear_user (tags,MTE_GRANULES_PER_PAGE );kvm_release_pfn_clean (pfn); }else { +/* +* Only locking to serialise with a concurrent +* set_pte_at() in the VMM but still overriding the +* tags, hence ignoring the return value. +*/ +try_page_mte_tagging (page); num_tags =mte_copy_tags_from_user (maddr, tags,MTE_GRANULES_PER_PAGE ); -/* -* Set the flag after checking the write -* completed fully -*/ -if (num_tags ==MTE_GRANULES_PER_PAGE ) -set_page_mte_tagged (page); +/* uaccess failed, don't leave stale tags */ +if (num_tags !=MTE_GRANULES_PER_PAGE ) +mte_clear_page_tags (page); +set_page_mte_tagged (page);kvm_release_pfn_dirty (pfn); }
arch/arm64/kvm/mmu.c +1 -1
@@ -1066,7 +1066,7 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,return ;for (i =0 ; i < nr_pages; i++, page++) { -if (!page_mte_tagged (page)) { +if (try_page_mte_tagging (page)) {mte_clear_page_tags (page_address (page));set_page_mte_tagged (page); }
arch/arm64/mm/copypage.c +2 -0
@@ -22,6 +22,8 @@ void copy_highpage(struct page *to, struct page *from)copy_page (kto, kfrom);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); }
arch/arm64/mm/fault.c +2 -0
@@ -930,6 +930,8 @@ struct page *alloc_zeroed_user_highpage_movable(struct vm_area_struct *vma,void tag_clear_highpage (struct page *page) { +/* Newly allocated page, shouldn't have been tagged yet */ +WARN_ON_ONCE (!try_page_mte_tagging (page));mte_zero_clear_page_tags (page_address (page));set_page_mte_tagged (page); }
arch/arm64/mm/mteswap.c +3 -0
@@ -53,6 +53,9 @@ bool mte_restore_tags(swp_entry_t entry, struct page *page)if (!tags)return false; +/* racing tag restoring? */ +if (!try_page_mte_tagging (page)) +return false;mte_restore_page_tags (page_address (page), tags);return true;
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
PATCH v2 5/7 KVM: arm64: unify the tests for VMAs in memslots when MTE is enabled
In reply to Peter CollingbournePreviously we allowed creating a memslot containing a private mapping that was not VM_MTE_ALLOWED, but would later reject KVM_RUN with -EFAULT. Now we reject the memory region at memslot creation time.
Since this is a minor tweak to the ABI (a VMM that created one of these memslots would fail later anyway), no VMM to my knowledge has MTE support yet, and the hardware with the necessary features is not generally available, we can probably make this ABI change at this point.
--- arch/arm64/kvm/mmu.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
arch/arm64/kvm/mmu.c +16 -9
@@ -1073,6 +1073,19 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn, } } +static bool kvm_vma_mte_allowed (struct vm_area_struct *vma) +{ +/* +* VM_SHARED mappings are not allowed with MTE to avoid races +* when updating the PG_mte_tagged page flag, see +* sanitise_mte_tags for more details. +*/ +if (vma->vm_flags &VM_SHARED ) +return false; + +return vma->vm_flags &VM_MTE_ALLOWED ; +} +static int user_mem_abort (struct kvm_vcpu *vcpu,phys_addr_t fault_ipa,struct kvm_memory_slot *memslot,unsigned long hva,unsigned long fault_status)
@@ -1249,9 +1262,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, }if (fault_status !=FSC_PERM && !device &&kvm_has_mte (kvm)) { -/* Check the VMM hasn't introduced a new VM_SHARED VMA */ -if ((vma->vm_flags &VM_MTE_ALLOWED ) && - !(vma->vm_flags &VM_SHARED )) { +/* Check the VMM hasn't introduced a new disallowed VMA */ +if (kvm_vma_mte_allowed (vma)) {sanitise_mte_tags (kvm, pfn, vma_pagesize); }else { ret = -EFAULT ;
@@ -1695,12 +1707,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,if (!vma)break ; -/* -* VM_SHARED mappings are not allowed with MTE to avoid races -* when updating the PG_mte_tagged page flag, see -* sanitise_mte_tags for more details. -*/ -if (kvm_has_mte (kvm) && vma->vm_flags &VM_SHARED ) { +if (kvm_has_mte (kvm) && !kvm_vma_mte_allowed (vma)) { ret = -EINVAL ;break ; }
Signature · 1 line
2.37.1.359.gd136c6c3e2-goog
PATCH v2 6/7 KVM: arm64: permit all VM_MTE_ALLOWED mappings with MTE enabled
In reply to Peter CollingbourneCertain VMMs such as crosvm have features (e.g. sandboxing) that depend on being able to map guest memory as MAP_SHARED. The current restriction on sharing MAP_SHARED pages with the guest is preventing the use of those features with MTE. Now that the races between tasks concurrently clearing tags on the same page have been fixed, remove this restriction.
--- arch/arm64/kvm/mmu.c | 8 -------- 1 file changed, 8 deletions(-)
arch/arm64/kvm/mmu.c +0 -8
@@ -1075,14 +1075,6 @@ static void sanitise_mte_tags(struct kvm *kvm, kvm_pfn_t pfn,static bool kvm_vma_mte_allowed (struct vm_area_struct *vma) { -/* -* VM_SHARED mappings are not allowed with MTE to avoid races -* when updating the PG_mte_tagged page flag, see -* sanitise_mte_tags for more details. -*/ -if (vma->vm_flags &VM_SHARED ) -return false; -return vma->vm_flags &VM_MTE_ALLOWED ; }
Signature · 6 lines
2.37.1.359.gd136c6c3e2-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
PATCH v2 7/7 Documentation: document the ABI changes for KVM_CAP_ARM_MTE
In reply to Peter CollingbourneDocument both the restriction on VM_MTE_ALLOWED mappings and the relaxation for shared mappings.
--- Documentation/virt/kvm/api.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
Documentation/virt/kvm/api.rst +3 -2
@@ -7486,8 +7486,9 @@ hibernation of the host; however the VMM needs to manually save/restore the tags as appropriate if the VM is migrated. When this capability is enabled all memory in memslots must be mapped as -not-shareable (no MAP_SHARED), attempts to create a memslot with a -MAP_SHARED mmap will result in an -EINVAL return. +``MAP_ANONYMOUS`` or with a RAM-based file mapping (``tmpfs``, ``memfd``), +attempts to create a memslot with an invalid mmap will result in an +-EINVAL return. When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to perform a bulk copy of tags to/from the guest.
Signature · 6 lines
2.37.1.359.gd136c6c3e2-goog _______________________________________________ kvmarm mailing list [email protected] https://lists.cs.columbia.edu/mailman/listinfo/kvmarm