Commit c22c3e07 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'mm-hotfixes-stable-2024-05-10-13-14' of...

Merge tag 'mm-hotfixes-stable-2024-05-10-13-14' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm

Pull MM fixes from Andrew Morton:
 "18 hotfixes, 7 of which are cc:stable.

  More fixups for this cycle's page_owner updates. And a few userfaultfd
  fixes. Otherwise, random singletons - see the individual changelogs
  for details"

* tag 'mm-hotfixes-stable-2024-05-10-13-14' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm:
  mailmap: add entry for Barry Song
  selftests/mm: fix powerpc ARCH check
  mailmap: add entry for John Garry
  XArray: set the marks correctly when splitting an entry
  selftests/vDSO: fix runtime errors on LoongArch
  selftests/vDSO: fix building errors on LoongArch
  mm,page_owner: don't remove __GFP_NOLOCKDEP in add_stack_record_to_list
  fs/proc/task_mmu: fix uffd-wp confusion in pagemap_scan_pmd_entry()
  fs/proc/task_mmu: fix loss of young/dirty bits during pagemap scan
  mm/vmalloc: fix return value of vb_alloc if size is 0
  mm: use memalloc_nofs_save() in page_cache_ra_order()
  kmsan: compiler_types: declare __no_sanitize_or_inline
  lib/test_xarray.c: fix error assumptions on check_xa_multi_store_adv_add()
  tools: fix userspace compilation with new test_xarray changes
  MAINTAINERS: update URL's for KEYS/KEYRINGS_INTEGRITY and TPM DEVICE DRIVER
  mm: page_owner: fix wrong information in dump_page_owner
  maple_tree: fix mas_empty_area_rev() null pointer dereference
  mm/userfaultfd: reset ptes when close() for wr-protected ones
parents cfb4be1a 672614a3
...@@ -97,6 +97,11 @@ Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@linaro.org> ...@@ -97,6 +97,11 @@ Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@linaro.org>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@spreadtrum.com> Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@spreadtrum.com>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@unisoc.com> Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang@unisoc.com>
Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang7@gmail.com> Baolin Wang <baolin.wang@linux.alibaba.com> <baolin.wang7@gmail.com>
Barry Song <baohua@kernel.org> <21cnbao@gmail.com>
Barry Song <baohua@kernel.org> <v-songbaohua@oppo.com>
Barry Song <baohua@kernel.org> <song.bao.hua@hisilicon.com>
Barry Song <baohua@kernel.org> <Baohua.Song@csr.com>
Barry Song <baohua@kernel.org> <barry.song@analog.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com> Bart Van Assche <bvanassche@acm.org> <bart.vanassche@sandisk.com>
Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com> Bart Van Assche <bvanassche@acm.org> <bart.vanassche@wdc.com>
Bartosz Golaszewski <brgl@bgdev.pl> <bgolaszewski@baylibre.com> Bartosz Golaszewski <brgl@bgdev.pl> <bgolaszewski@baylibre.com>
...@@ -304,6 +309,7 @@ Johan Hovold <johan@kernel.org> <jhovold@gmail.com> ...@@ -304,6 +309,7 @@ Johan Hovold <johan@kernel.org> <jhovold@gmail.com>
Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com> Johan Hovold <johan@kernel.org> <johan@hovoldconsulting.com>
John Crispin <john@phrozen.org> <blogic@openwrt.org> John Crispin <john@phrozen.org> <blogic@openwrt.org>
John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com> John Fastabend <john.fastabend@gmail.com> <john.r.fastabend@intel.com>
John Garry <john.g.garry@oracle.com> <john.garry@huawei.com>
John Keeping <john@keeping.me.uk> <john@metanate.com> John Keeping <john@keeping.me.uk> <john@metanate.com>
John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com> John Moon <john@jmoon.dev> <quic_johmoo@quicinc.com>
John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de> John Paul Adrian Glaubitz <glaubitz@physik.fu-berlin.de>
......
...@@ -12041,6 +12041,7 @@ M: Mimi Zohar <zohar@linux.ibm.com> ...@@ -12041,6 +12041,7 @@ M: Mimi Zohar <zohar@linux.ibm.com>
L: linux-integrity@vger.kernel.org L: linux-integrity@vger.kernel.org
L: keyrings@vger.kernel.org L: keyrings@vger.kernel.org
S: Supported S: Supported
W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity
F: security/integrity/platform_certs F: security/integrity/platform_certs
KFENCE KFENCE
...@@ -22409,7 +22410,7 @@ M: Jarkko Sakkinen <jarkko@kernel.org> ...@@ -22409,7 +22410,7 @@ M: Jarkko Sakkinen <jarkko@kernel.org>
R: Jason Gunthorpe <jgg@ziepe.ca> R: Jason Gunthorpe <jgg@ziepe.ca>
L: linux-integrity@vger.kernel.org L: linux-integrity@vger.kernel.org
S: Maintained S: Maintained
W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity W: https://gitlab.com/jarkkojs/linux-tpmdd-test
Q: https://patchwork.kernel.org/project/linux-integrity/list/ Q: https://patchwork.kernel.org/project/linux-integrity/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git
F: Documentation/devicetree/bindings/tpm/ F: Documentation/devicetree/bindings/tpm/
......
...@@ -1817,15 +1817,13 @@ static unsigned long pagemap_page_category(struct pagemap_scan_private *p, ...@@ -1817,15 +1817,13 @@ static unsigned long pagemap_page_category(struct pagemap_scan_private *p,
} }
static void make_uffd_wp_pte(struct vm_area_struct *vma, static void make_uffd_wp_pte(struct vm_area_struct *vma,
unsigned long addr, pte_t *pte) unsigned long addr, pte_t *pte, pte_t ptent)
{ {
pte_t ptent = ptep_get(pte);
if (pte_present(ptent)) { if (pte_present(ptent)) {
pte_t old_pte; pte_t old_pte;
old_pte = ptep_modify_prot_start(vma, addr, pte); old_pte = ptep_modify_prot_start(vma, addr, pte);
ptent = pte_mkuffd_wp(ptent); ptent = pte_mkuffd_wp(old_pte);
ptep_modify_prot_commit(vma, addr, pte, old_pte, ptent); ptep_modify_prot_commit(vma, addr, pte, old_pte, ptent);
} else if (is_swap_pte(ptent)) { } else if (is_swap_pte(ptent)) {
ptent = pte_swp_mkuffd_wp(ptent); ptent = pte_swp_mkuffd_wp(ptent);
...@@ -2175,9 +2173,12 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start, ...@@ -2175,9 +2173,12 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
if ((p->arg.flags & PM_SCAN_WP_MATCHING) && !p->vec_out) { if ((p->arg.flags & PM_SCAN_WP_MATCHING) && !p->vec_out) {
/* Fast path for performing exclusive WP */ /* Fast path for performing exclusive WP */
for (addr = start; addr != end; pte++, addr += PAGE_SIZE) { for (addr = start; addr != end; pte++, addr += PAGE_SIZE) {
if (pte_uffd_wp(ptep_get(pte))) pte_t ptent = ptep_get(pte);
if ((pte_present(ptent) && pte_uffd_wp(ptent)) ||
pte_swp_uffd_wp_any(ptent))
continue; continue;
make_uffd_wp_pte(vma, addr, pte); make_uffd_wp_pte(vma, addr, pte, ptent);
if (!flush_end) if (!flush_end)
start = addr; start = addr;
flush_end = addr + PAGE_SIZE; flush_end = addr + PAGE_SIZE;
...@@ -2190,8 +2191,10 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start, ...@@ -2190,8 +2191,10 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
p->arg.return_mask == PAGE_IS_WRITTEN) { p->arg.return_mask == PAGE_IS_WRITTEN) {
for (addr = start; addr < end; pte++, addr += PAGE_SIZE) { for (addr = start; addr < end; pte++, addr += PAGE_SIZE) {
unsigned long next = addr + PAGE_SIZE; unsigned long next = addr + PAGE_SIZE;
pte_t ptent = ptep_get(pte);
if (pte_uffd_wp(ptep_get(pte))) if ((pte_present(ptent) && pte_uffd_wp(ptent)) ||
pte_swp_uffd_wp_any(ptent))
continue; continue;
ret = pagemap_scan_output(p->cur_vma_category | PAGE_IS_WRITTEN, ret = pagemap_scan_output(p->cur_vma_category | PAGE_IS_WRITTEN,
p, addr, &next); p, addr, &next);
...@@ -2199,7 +2202,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start, ...@@ -2199,7 +2202,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
break; break;
if (~p->arg.flags & PM_SCAN_WP_MATCHING) if (~p->arg.flags & PM_SCAN_WP_MATCHING)
continue; continue;
make_uffd_wp_pte(vma, addr, pte); make_uffd_wp_pte(vma, addr, pte, ptent);
if (!flush_end) if (!flush_end)
start = addr; start = addr;
flush_end = next; flush_end = next;
...@@ -2208,8 +2211,9 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start, ...@@ -2208,8 +2211,9 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
} }
for (addr = start; addr != end; pte++, addr += PAGE_SIZE) { for (addr = start; addr != end; pte++, addr += PAGE_SIZE) {
pte_t ptent = ptep_get(pte);
unsigned long categories = p->cur_vma_category | unsigned long categories = p->cur_vma_category |
pagemap_page_category(p, vma, addr, ptep_get(pte)); pagemap_page_category(p, vma, addr, ptent);
unsigned long next = addr + PAGE_SIZE; unsigned long next = addr + PAGE_SIZE;
if (!pagemap_scan_is_interesting_page(categories, p)) if (!pagemap_scan_is_interesting_page(categories, p))
...@@ -2224,7 +2228,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start, ...@@ -2224,7 +2228,7 @@ static int pagemap_scan_pmd_entry(pmd_t *pmd, unsigned long start,
if (~categories & PAGE_IS_WRITTEN) if (~categories & PAGE_IS_WRITTEN)
continue; continue;
make_uffd_wp_pte(vma, addr, pte); make_uffd_wp_pte(vma, addr, pte, ptent);
if (!flush_end) if (!flush_end)
start = addr; start = addr;
flush_end = next; flush_end = next;
......
...@@ -895,6 +895,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file) ...@@ -895,6 +895,10 @@ static int userfaultfd_release(struct inode *inode, struct file *file)
prev = vma; prev = vma;
continue; continue;
} }
/* Reset ptes for the whole vma range if wr-protected */
if (userfaultfd_wp(vma))
uffd_wp_range(vma, vma->vm_start,
vma->vm_end - vma->vm_start, false);
new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS; new_flags = vma->vm_flags & ~__VM_UFFD_FLAGS;
vma = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start, vma = vma_modify_flags_uffd(&vmi, prev, vma, vma->vm_start,
vma->vm_end, new_flags, vma->vm_end, new_flags,
......
...@@ -278,6 +278,17 @@ struct ftrace_likely_data { ...@@ -278,6 +278,17 @@ struct ftrace_likely_data {
# define __no_kcsan # define __no_kcsan
#endif #endif
#ifdef __SANITIZE_MEMORY__
/*
* Similarly to KASAN and KCSAN, KMSAN loses function attributes of inlined
* functions, therefore disabling KMSAN checks also requires disabling inlining.
*
* __no_sanitize_or_inline effectively prevents KMSAN from reporting errors
* within the function and marks all its outputs as initialized.
*/
# define __no_sanitize_or_inline __no_kmsan_checks notrace __maybe_unused
#endif
#ifndef __no_sanitize_or_inline #ifndef __no_sanitize_or_inline
#define __no_sanitize_or_inline __always_inline #define __no_sanitize_or_inline __always_inline
#endif #endif
......
...@@ -5109,18 +5109,18 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min, ...@@ -5109,18 +5109,18 @@ int mas_empty_area_rev(struct ma_state *mas, unsigned long min,
if (size == 0 || max - min < size - 1) if (size == 0 || max - min < size - 1)
return -EINVAL; return -EINVAL;
if (mas_is_start(mas)) { if (mas_is_start(mas))
mas_start(mas); mas_start(mas);
mas->offset = mas_data_end(mas); else if ((mas->offset < 2) && (!mas_rewind_node(mas)))
} else if (mas->offset >= 2) {
mas->offset -= 2;
} else if (!mas_rewind_node(mas)) {
return -EBUSY; return -EBUSY;
}
/* Empty set. */ if (unlikely(mas_is_none(mas) || mas_is_ptr(mas)))
if (mas_is_none(mas) || mas_is_ptr(mas))
return mas_sparse_area(mas, min, max, size, false); return mas_sparse_area(mas, min, max, size, false);
else if (mas->offset >= 2)
mas->offset -= 2;
else
mas->offset = mas_data_end(mas);
/* The start of the window can only be within these values. */ /* The start of the window can only be within these values. */
mas->index = min; mas->index = min;
......
...@@ -744,15 +744,20 @@ static noinline void check_xa_multi_store_adv_add(struct xarray *xa, ...@@ -744,15 +744,20 @@ static noinline void check_xa_multi_store_adv_add(struct xarray *xa,
do { do {
xas_lock_irq(&xas); xas_lock_irq(&xas);
xas_store(&xas, p); xas_store(&xas, p);
XA_BUG_ON(xa, xas_error(&xas));
XA_BUG_ON(xa, xa_load(xa, index) != p);
xas_unlock_irq(&xas); xas_unlock_irq(&xas);
/*
* In our selftest case the only failure we can expect is for
* there not to be enough memory as we're not mimicking the
* entire page cache, so verify that's the only error we can run
* into here. The xas_nomem() which follows will ensure to fix
* that condition for us so to chug on on the loop.
*/
XA_BUG_ON(xa, xas_error(&xas) && xas_error(&xas) != -ENOMEM);
} while (xas_nomem(&xas, GFP_KERNEL)); } while (xas_nomem(&xas, GFP_KERNEL));
XA_BUG_ON(xa, xas_error(&xas)); XA_BUG_ON(xa, xas_error(&xas));
XA_BUG_ON(xa, xa_load(xa, index) != p);
} }
/* mimics page_cache_delete() */ /* mimics page_cache_delete() */
...@@ -1783,9 +1788,11 @@ static void check_split_1(struct xarray *xa, unsigned long index, ...@@ -1783,9 +1788,11 @@ static void check_split_1(struct xarray *xa, unsigned long index,
unsigned int order, unsigned int new_order) unsigned int order, unsigned int new_order)
{ {
XA_STATE_ORDER(xas, xa, index, new_order); XA_STATE_ORDER(xas, xa, index, new_order);
unsigned int i; unsigned int i, found;
void *entry;
xa_store_order(xa, index, order, xa, GFP_KERNEL); xa_store_order(xa, index, order, xa, GFP_KERNEL);
xa_set_mark(xa, index, XA_MARK_1);
xas_split_alloc(&xas, xa, order, GFP_KERNEL); xas_split_alloc(&xas, xa, order, GFP_KERNEL);
xas_lock(&xas); xas_lock(&xas);
...@@ -1802,6 +1809,16 @@ static void check_split_1(struct xarray *xa, unsigned long index, ...@@ -1802,6 +1809,16 @@ static void check_split_1(struct xarray *xa, unsigned long index,
xa_set_mark(xa, index, XA_MARK_0); xa_set_mark(xa, index, XA_MARK_0);
XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0)); XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0));
xas_set_order(&xas, index, 0);
found = 0;
rcu_read_lock();
xas_for_each_marked(&xas, entry, ULONG_MAX, XA_MARK_1) {
found++;
XA_BUG_ON(xa, xa_is_internal(entry));
}
rcu_read_unlock();
XA_BUG_ON(xa, found != 1 << (order - new_order));
xa_destroy(xa); xa_destroy(xa);
} }
......
...@@ -969,8 +969,22 @@ static unsigned int node_get_marks(struct xa_node *node, unsigned int offset) ...@@ -969,8 +969,22 @@ static unsigned int node_get_marks(struct xa_node *node, unsigned int offset)
return marks; return marks;
} }
static inline void node_mark_slots(struct xa_node *node, unsigned int sibs,
xa_mark_t mark)
{
int i;
if (sibs == 0)
node_mark_all(node, mark);
else {
for (i = 0; i < XA_CHUNK_SIZE; i += sibs + 1)
node_set_mark(node, i, mark);
}
}
static void node_set_marks(struct xa_node *node, unsigned int offset, static void node_set_marks(struct xa_node *node, unsigned int offset,
struct xa_node *child, unsigned int marks) struct xa_node *child, unsigned int sibs,
unsigned int marks)
{ {
xa_mark_t mark = XA_MARK_0; xa_mark_t mark = XA_MARK_0;
...@@ -978,7 +992,7 @@ static void node_set_marks(struct xa_node *node, unsigned int offset, ...@@ -978,7 +992,7 @@ static void node_set_marks(struct xa_node *node, unsigned int offset,
if (marks & (1 << (__force unsigned int)mark)) { if (marks & (1 << (__force unsigned int)mark)) {
node_set_mark(node, offset, mark); node_set_mark(node, offset, mark);
if (child) if (child)
node_mark_all(child, mark); node_mark_slots(child, sibs, mark);
} }
if (mark == XA_MARK_MAX) if (mark == XA_MARK_MAX)
break; break;
...@@ -1077,7 +1091,8 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order) ...@@ -1077,7 +1091,8 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
child->nr_values = xa_is_value(entry) ? child->nr_values = xa_is_value(entry) ?
XA_CHUNK_SIZE : 0; XA_CHUNK_SIZE : 0;
RCU_INIT_POINTER(child->parent, node); RCU_INIT_POINTER(child->parent, node);
node_set_marks(node, offset, child, marks); node_set_marks(node, offset, child, xas->xa_sibs,
marks);
rcu_assign_pointer(node->slots[offset], rcu_assign_pointer(node->slots[offset],
xa_mk_node(child)); xa_mk_node(child));
if (xa_is_value(curr)) if (xa_is_value(curr))
...@@ -1086,7 +1101,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order) ...@@ -1086,7 +1101,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
} else { } else {
unsigned int canon = offset - xas->xa_sibs; unsigned int canon = offset - xas->xa_sibs;
node_set_marks(node, canon, NULL, marks); node_set_marks(node, canon, NULL, 0, marks);
rcu_assign_pointer(node->slots[canon], entry); rcu_assign_pointer(node->slots[canon], entry);
while (offset > canon) while (offset > canon)
rcu_assign_pointer(node->slots[offset--], rcu_assign_pointer(node->slots[offset--],
......
...@@ -170,7 +170,7 @@ static void add_stack_record_to_list(struct stack_record *stack_record, ...@@ -170,7 +170,7 @@ static void add_stack_record_to_list(struct stack_record *stack_record,
/* Filter gfp_mask the same way stackdepot does, for consistency */ /* Filter gfp_mask the same way stackdepot does, for consistency */
gfp_mask &= ~GFP_ZONEMASK; gfp_mask &= ~GFP_ZONEMASK;
gfp_mask &= (GFP_ATOMIC | GFP_KERNEL); gfp_mask &= (GFP_ATOMIC | GFP_KERNEL | __GFP_NOLOCKDEP);
gfp_mask |= __GFP_NOWARN; gfp_mask |= __GFP_NOWARN;
set_current_in_page_owner(); set_current_in_page_owner();
...@@ -328,7 +328,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order, ...@@ -328,7 +328,7 @@ noinline void __set_page_owner(struct page *page, unsigned short order,
if (unlikely(!page_ext)) if (unlikely(!page_ext))
return; return;
__update_page_owner_handle(page_ext, handle, order, gfp_mask, -1, __update_page_owner_handle(page_ext, handle, order, gfp_mask, -1,
current->pid, current->tgid, ts_nsec, ts_nsec, current->pid, current->tgid,
current->comm); current->comm);
page_ext_put(page_ext); page_ext_put(page_ext);
inc_stack_record_count(handle, gfp_mask, 1 << order); inc_stack_record_count(handle, gfp_mask, 1 << order);
......
...@@ -490,6 +490,7 @@ void page_cache_ra_order(struct readahead_control *ractl, ...@@ -490,6 +490,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
pgoff_t index = readahead_index(ractl); pgoff_t index = readahead_index(ractl);
pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT; pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT;
pgoff_t mark = index + ra->size - ra->async_size; pgoff_t mark = index + ra->size - ra->async_size;
unsigned int nofs;
int err = 0; int err = 0;
gfp_t gfp = readahead_gfp_mask(mapping); gfp_t gfp = readahead_gfp_mask(mapping);
...@@ -504,6 +505,8 @@ void page_cache_ra_order(struct readahead_control *ractl, ...@@ -504,6 +505,8 @@ void page_cache_ra_order(struct readahead_control *ractl,
new_order = min_t(unsigned int, new_order, ilog2(ra->size)); new_order = min_t(unsigned int, new_order, ilog2(ra->size));
} }
/* See comment in page_cache_ra_unbounded() */
nofs = memalloc_nofs_save();
filemap_invalidate_lock_shared(mapping); filemap_invalidate_lock_shared(mapping);
while (index <= limit) { while (index <= limit) {
unsigned int order = new_order; unsigned int order = new_order;
...@@ -527,6 +530,7 @@ void page_cache_ra_order(struct readahead_control *ractl, ...@@ -527,6 +530,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
read_pages(ractl); read_pages(ractl);
filemap_invalidate_unlock_shared(mapping); filemap_invalidate_unlock_shared(mapping);
memalloc_nofs_restore(nofs);
/* /*
* If there were already pages in the page cache, then we may have * If there were already pages in the page cache, then we may have
......
...@@ -2710,7 +2710,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask) ...@@ -2710,7 +2710,7 @@ static void *vb_alloc(unsigned long size, gfp_t gfp_mask)
* get_order(0) returns funny result. Just warn and terminate * get_order(0) returns funny result. Just warn and terminate
* early. * early.
*/ */
return NULL; return ERR_PTR(-EINVAL);
} }
order = get_order(size); order = get_order(size);
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#define pr_info printk #define pr_info printk
#define pr_debug printk #define pr_debug printk
#define pr_cont printk #define pr_cont printk
#define schedule()
#define PAGE_SHIFT 12
#define __acquires(x) #define __acquires(x)
#define __releases(x) #define __releases(x)
......
...@@ -12,7 +12,7 @@ uname_M := $(shell uname -m 2>/dev/null || echo not) ...@@ -12,7 +12,7 @@ uname_M := $(shell uname -m 2>/dev/null || echo not)
else else
uname_M := $(shell echo $(CROSS_COMPILE) | grep -o '^[a-z0-9]\+') uname_M := $(shell echo $(CROSS_COMPILE) | grep -o '^[a-z0-9]\+')
endif endif
ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/ppc64/') ARCH ?= $(shell echo $(uname_M) | sed -e 's/aarch64.*/arm64/' -e 's/ppc64.*/powerpc/')
endif endif
# Without this, failed build products remain, with up-to-date timestamps, # Without this, failed build products remain, with up-to-date timestamps,
...@@ -98,13 +98,13 @@ TEST_GEN_FILES += $(BINARIES_64) ...@@ -98,13 +98,13 @@ TEST_GEN_FILES += $(BINARIES_64)
endif endif
else else
ifneq (,$(findstring $(ARCH),ppc64)) ifneq (,$(findstring $(ARCH),powerpc))
TEST_GEN_FILES += protection_keys TEST_GEN_FILES += protection_keys
endif endif
endif endif
ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 ppc64 riscv64 s390x sparc64 x86_64)) ifneq (,$(filter $(ARCH),arm64 ia64 mips64 parisc64 powerpc riscv64 s390x sparc64 x86_64))
TEST_GEN_FILES += va_high_addr_switch TEST_GEN_FILES += va_high_addr_switch
TEST_GEN_FILES += virtual_address_range TEST_GEN_FILES += virtual_address_range
TEST_GEN_FILES += write_to_hugetlbfs TEST_GEN_FILES += write_to_hugetlbfs
......
...@@ -53,15 +53,19 @@ ...@@ -53,15 +53,19 @@
#if __riscv_xlen == 32 #if __riscv_xlen == 32
#define VDSO_32BIT 1 #define VDSO_32BIT 1
#endif #endif
#elif defined(__loongarch__)
#define VDSO_VERSION 6
#define VDSO_NAMES 1
#endif #endif
static const char *versions[6] = { static const char *versions[7] = {
"LINUX_2.6", "LINUX_2.6",
"LINUX_2.6.15", "LINUX_2.6.15",
"LINUX_2.6.29", "LINUX_2.6.29",
"LINUX_2.6.39", "LINUX_2.6.39",
"LINUX_4", "LINUX_4",
"LINUX_4.15", "LINUX_4.15",
"LINUX_5.10"
}; };
static const char *names[2][6] = { static const char *names[2][6] = {
......
...@@ -13,13 +13,7 @@ ...@@ -13,13 +13,7 @@
#include "../kselftest.h" #include "../kselftest.h"
#include "parse_vdso.h" #include "parse_vdso.h"
#include "vdso_config.h"
#if defined(__riscv)
const char *version = "LINUX_4.15";
#else
const char *version = "LINUX_2.6";
#endif
const char *name = "__vdso_getcpu";
struct getcpu_cache; struct getcpu_cache;
typedef long (*getcpu_t)(unsigned int *, unsigned int *, typedef long (*getcpu_t)(unsigned int *, unsigned int *,
...@@ -27,6 +21,8 @@ typedef long (*getcpu_t)(unsigned int *, unsigned int *, ...@@ -27,6 +21,8 @@ typedef long (*getcpu_t)(unsigned int *, unsigned int *,
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *version = versions[VDSO_VERSION];
const char **name = (const char **)&names[VDSO_NAMES];
unsigned long sysinfo_ehdr; unsigned long sysinfo_ehdr;
unsigned int cpu, node; unsigned int cpu, node;
getcpu_t get_cpu; getcpu_t get_cpu;
...@@ -40,9 +36,9 @@ int main(int argc, char **argv) ...@@ -40,9 +36,9 @@ int main(int argc, char **argv)
vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR)); vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
get_cpu = (getcpu_t)vdso_sym(version, name); get_cpu = (getcpu_t)vdso_sym(version, name[4]);
if (!get_cpu) { if (!get_cpu) {
printf("Could not find %s\n", name); printf("Could not find %s\n", name[4]);
return KSFT_SKIP; return KSFT_SKIP;
} }
...@@ -50,7 +46,7 @@ int main(int argc, char **argv) ...@@ -50,7 +46,7 @@ int main(int argc, char **argv)
if (ret == 0) { if (ret == 0) {
printf("Running on CPU %u node %u\n", cpu, node); printf("Running on CPU %u node %u\n", cpu, node);
} else { } else {
printf("%s failed\n", name); printf("%s failed\n", name[4]);
return KSFT_FAIL; return KSFT_FAIL;
} }
......
...@@ -18,25 +18,13 @@ ...@@ -18,25 +18,13 @@
#include "../kselftest.h" #include "../kselftest.h"
#include "parse_vdso.h" #include "parse_vdso.h"
#include "vdso_config.h"
/*
* ARM64's vDSO exports its gettimeofday() implementation with a different
* name and version from other architectures, so we need to handle it as
* a special case.
*/
#if defined(__aarch64__)
const char *version = "LINUX_2.6.39";
const char *name = "__kernel_gettimeofday";
#elif defined(__riscv)
const char *version = "LINUX_4.15";
const char *name = "__vdso_gettimeofday";
#else
const char *version = "LINUX_2.6";
const char *name = "__vdso_gettimeofday";
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
const char *version = versions[VDSO_VERSION];
const char **name = (const char **)&names[VDSO_NAMES];
unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR); unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
if (!sysinfo_ehdr) { if (!sysinfo_ehdr) {
printf("AT_SYSINFO_EHDR is not present!\n"); printf("AT_SYSINFO_EHDR is not present!\n");
...@@ -47,10 +35,10 @@ int main(int argc, char **argv) ...@@ -47,10 +35,10 @@ int main(int argc, char **argv)
/* Find gettimeofday. */ /* Find gettimeofday. */
typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz); typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
gtod_t gtod = (gtod_t)vdso_sym(version, name); gtod_t gtod = (gtod_t)vdso_sym(version, name[0]);
if (!gtod) { if (!gtod) {
printf("Could not find %s\n", name); printf("Could not find %s\n", name[0]);
return KSFT_SKIP; return KSFT_SKIP;
} }
...@@ -61,7 +49,7 @@ int main(int argc, char **argv) ...@@ -61,7 +49,7 @@ int main(int argc, char **argv)
printf("The time is %lld.%06lld\n", printf("The time is %lld.%06lld\n",
(long long)tv.tv_sec, (long long)tv.tv_usec); (long long)tv.tv_sec, (long long)tv.tv_usec);
} else { } else {
printf("%s failed\n", name); printf("%s failed\n", name[0]);
return KSFT_FAIL; return KSFT_FAIL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment