ANDROID: 16K: Fixup perf_mmap check for metadata page

perf_mmap() expects a power of 2 number of pages plus 1 additional page.

In the emulated __PAGE_SIZE case, the one extra page is actually
  (__PAGE_SIZE / PAGE_SIZE) number of 4KiB pages in the kernel.

See MMAP layout in perf_event_open():

       The mmap size should be 1+2^n pages, where the first page is a
       metadata page (struct perf_event_mmap_page) that contains various
       bits of information such as where the ring-buffer head is. [1]

Also update perf_event_mmap_kb's default value to reflect this;
    i.e 512KiB + sizeof 1 page in KiB (__PAGE_SIZE/1024)

[1] https://man7.org/linux/man-pages/man2/perf_event_open.2.html

Bug: 383389337
Bug: 366098040
Test: atest vts_ltp_test_x86_64
Change-Id: I475e3c9ed896d8e3735681b1143e31c62ed20359
Signed-off-by: Kalesh Singh <kaleshsingh@google.com>
This commit is contained in:
Kalesh Singh
2024-10-04 16:00:19 -07:00
committed by Carlos Llamas
parent 03ce5534fc
commit 13ba0aec9c
2 changed files with 16 additions and 2 deletions

View File

@@ -46,6 +46,7 @@
#include <linux/filter.h>
#include <linux/namei.h>
#include <linux/parser.h>
#include <linux/page_size_compat.h>
#include <linux/sched/clock.h>
#include <linux/sched/mm.h>
#include <linux/proc_ns.h>
@@ -6628,7 +6629,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
vma_size = vma->vm_end - vma->vm_start;
if (vma->vm_pgoff == 0) {
nr_pages = (vma_size / PAGE_SIZE) - 1;
nr_pages = (vma_size / PAGE_SIZE) - (__PAGE_SIZE / PAGE_SIZE);
} else {
/*
* AUX area mapping: if rb->aux_nr_pages != 0, it's already
@@ -6699,7 +6700,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
if (nr_pages != 0 && !is_power_of_2(nr_pages))
return -EINVAL;
if (vma_size != PAGE_SIZE * (1 + nr_pages))
if (vma_size != PAGE_SIZE * ((__PAGE_SIZE / PAGE_SIZE) + nr_pages))
return -EINVAL;
WARN_ON_ONCE(event->ctx->parent_ctx);

View File

@@ -13,6 +13,7 @@
#include <linux/pagemap.h>
#include <linux/page_size_compat.h>
#include <linux/swap.h>
#include <linux/perf_event.h>
#define MIN_PAGE_SHIFT_COMPAT (PAGE_SHIFT + 1)
#define MAX_PAGE_SHIFT_COMPAT 16 /* Max of 64KB */
@@ -315,3 +316,15 @@ free_magic:
return error;
}
static int __init init_sysctl_perf_event_mlock(void)
{
if (!static_branch_unlikely(&page_shift_compat_enabled))
return 0;
/* Minimum for 512 kiB + 1 user control page */
sysctl_perf_event_mlock = 512 + (__PAGE_SIZE / 1024); /* 'free' kiB per user */
return 0;
}
core_initcall(init_sysctl_perf_event_mlock);