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:
committed by
Carlos Llamas
parent
03ce5534fc
commit
13ba0aec9c
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user