Skip to content

Commit 428e106

Browse files
kirylhansendc
authored andcommitted
mm: Introduce untagged_addr_remote()
untagged_addr() removes tags/metadata from the address and brings it to the canonical form. The helper is implemented on arm64 and sparc. Both of them do untagging based on global rules. However, Linear Address Masking (LAM) on x86 introduces per-process settings for untagging. As a result, untagged_addr() is now only suitable for untagging addresses for the current proccess. The new helper untagged_addr_remote() has to be used when the address targets remote process. It requires the mmap lock for target mm to be taken. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Tested-by: Alexander Potapenko <glider@google.com> Link: https://lore.kernel.org/all/20230312112612.31869-6-kirill.shutemov%40linux.intel.com
1 parent 82721d8 commit 428e106

8 files changed

Lines changed: 43 additions & 23 deletions

File tree

arch/sparc/include/asm/uaccess_64.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
#include <linux/compiler.h>
1010
#include <linux/string.h>
11+
#include <linux/mm_types.h>
1112
#include <asm/asi.h>
1213
#include <asm/spitfire.h>
14+
#include <asm/pgtable.h>
1315

1416
#include <asm/processor.h>
1517
#include <asm-generic/access_ok.h>

drivers/vfio/vfio_iommu_type1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
580580
goto done;
581581
}
582582

583-
vaddr = untagged_addr(vaddr);
583+
vaddr = untagged_addr_remote(mm, vaddr);
584584

585585
retry:
586586
vma = vma_lookup(mm, vaddr);

fs/proc/task_mmu.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,8 +1689,13 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
16891689

16901690
/* watch out for wraparound */
16911691
start_vaddr = end_vaddr;
1692-
if (svpfn <= (ULONG_MAX >> PAGE_SHIFT))
1693-
start_vaddr = untagged_addr(svpfn << PAGE_SHIFT);
1692+
if (svpfn <= (ULONG_MAX >> PAGE_SHIFT)) {
1693+
ret = mmap_read_lock_killable(mm);
1694+
if (ret)
1695+
goto out_free;
1696+
start_vaddr = untagged_addr_remote(mm, svpfn << PAGE_SHIFT);
1697+
mmap_read_unlock(mm);
1698+
}
16941699

16951700
/* Ensure the address is inside the task */
16961701
if (start_vaddr > mm->task_size)

include/linux/mm.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,17 +96,6 @@ extern int mmap_rnd_compat_bits __read_mostly;
9696
#include <asm/page.h>
9797
#include <asm/processor.h>
9898

99-
/*
100-
* Architectures that support memory tagging (assigning tags to memory regions,
101-
* embedding these tags into addresses that point to these memory regions, and
102-
* checking that the memory and the pointer tags match on memory accesses)
103-
* redefine this macro to strip tags from pointers.
104-
* It's defined as noop for architectures that don't support memory tagging.
105-
*/
106-
#ifndef untagged_addr
107-
#define untagged_addr(addr) (addr)
108-
#endif
109-
11099
#ifndef __pa_symbol
111100
#define __pa_symbol(x) __pa(RELOC_HIDE((unsigned long)(x), 0))
112101
#endif

include/linux/uaccess.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,28 @@
1010

1111
#include <asm/uaccess.h>
1212

13+
/*
14+
* Architectures that support memory tagging (assigning tags to memory regions,
15+
* embedding these tags into addresses that point to these memory regions, and
16+
* checking that the memory and the pointer tags match on memory accesses)
17+
* redefine this macro to strip tags from pointers.
18+
*
19+
* Passing down mm_struct allows to define untagging rules on per-process
20+
* basis.
21+
*
22+
* It's defined as noop for architectures that don't support memory tagging.
23+
*/
24+
#ifndef untagged_addr
25+
#define untagged_addr(addr) (addr)
26+
#endif
27+
28+
#ifndef untagged_addr_remote
29+
#define untagged_addr_remote(mm, addr) ({ \
30+
mmap_assert_locked(mm); \
31+
untagged_addr(addr); \
32+
})
33+
#endif
34+
1335
/*
1436
* Architectures should provide two primitives (raw_copy_{to,from}_user())
1537
* and get rid of their private instances of copy_{to,from}_user() and

mm/gup.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ static long __get_user_pages(struct mm_struct *mm,
10851085
if (!nr_pages)
10861086
return 0;
10871087

1088-
start = untagged_addr(start);
1088+
start = untagged_addr_remote(mm, start);
10891089

10901090
VM_BUG_ON(!!pages != !!(gup_flags & (FOLL_GET | FOLL_PIN)));
10911091

@@ -1259,7 +1259,7 @@ int fixup_user_fault(struct mm_struct *mm,
12591259
struct vm_area_struct *vma;
12601260
vm_fault_t ret;
12611261

1262-
address = untagged_addr(address);
1262+
address = untagged_addr_remote(mm, address);
12631263

12641264
if (unlocked)
12651265
fault_flags |= FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;

mm/madvise.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,8 +1402,6 @@ int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int beh
14021402
size_t len;
14031403
struct blk_plug plug;
14041404

1405-
start = untagged_addr(start);
1406-
14071405
if (!madvise_behavior_valid(behavior))
14081406
return -EINVAL;
14091407

@@ -1435,6 +1433,9 @@ int do_madvise(struct mm_struct *mm, unsigned long start, size_t len_in, int beh
14351433
mmap_read_lock(mm);
14361434
}
14371435

1436+
start = untagged_addr_remote(mm, start);
1437+
end = start + len;
1438+
14381439
blk_start_plug(&plug);
14391440
error = madvise_walk_vmas(mm, start, end, behavior,
14401441
madvise_vma_behavior);

mm/migrate.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2097,15 +2097,18 @@ static int do_move_pages_to_node(struct mm_struct *mm,
20972097
* target node
20982098
* 1 - when it has been queued
20992099
*/
2100-
static int add_page_for_migration(struct mm_struct *mm, unsigned long addr,
2100+
static int add_page_for_migration(struct mm_struct *mm, const void __user *p,
21012101
int node, struct list_head *pagelist, bool migrate_all)
21022102
{
21032103
struct vm_area_struct *vma;
2104+
unsigned long addr;
21042105
struct page *page;
21052106
int err;
21062107
bool isolated;
21072108

21082109
mmap_read_lock(mm);
2110+
addr = (unsigned long)untagged_addr_remote(mm, p);
2111+
21092112
err = -EFAULT;
21102113
vma = vma_lookup(mm, addr);
21112114
if (!vma || !vma_migratable(vma))
@@ -2211,15 +2214,13 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
22112214

22122215
for (i = start = 0; i < nr_pages; i++) {
22132216
const void __user *p;
2214-
unsigned long addr;
22152217
int node;
22162218

22172219
err = -EFAULT;
22182220
if (get_user(p, pages + i))
22192221
goto out_flush;
22202222
if (get_user(node, nodes + i))
22212223
goto out_flush;
2222-
addr = (unsigned long)untagged_addr(p);
22232224

22242225
err = -ENODEV;
22252226
if (node < 0 || node >= MAX_NUMNODES)
@@ -2247,8 +2248,8 @@ static int do_pages_move(struct mm_struct *mm, nodemask_t task_nodes,
22472248
* Errors in the page lookup or isolation are not fatal and we simply
22482249
* report them via status
22492250
*/
2250-
err = add_page_for_migration(mm, addr, current_node,
2251-
&pagelist, flags & MPOL_MF_MOVE_ALL);
2251+
err = add_page_for_migration(mm, p, current_node, &pagelist,
2252+
flags & MPOL_MF_MOVE_ALL);
22522253

22532254
if (err > 0) {
22542255
/* The page is successfully queued for migration */

0 commit comments

Comments
 (0)