Skip to content

Commit eb2dcde

Browse files
vdonnefortrostedt
authored andcommitted
ring-buffer: Align meta-page to sub-buffers for improved TLB usage
Previously, the mapped ring-buffer layout caused misalignment between the meta-page and sub-buffers when the sub-buffer size was not a multiple of PAGE_SIZE. This prevented hardware with larger TLB entries from utilizing them effectively. Add a padding with the zero-page between the meta-page and sub-buffers. Also update the ring-buffer map_test to verify that padding. Link: https://lore.kernel.org/[email protected] Signed-off-by: Vincent Donnefort <[email protected]> Signed-off-by: Steven Rostedt (Google) <[email protected]>
1 parent d0f2d6e commit eb2dcde

File tree

2 files changed

+34
-13
lines changed

2 files changed

+34
-13
lines changed

kernel/trace/ring_buffer.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6852,10 +6852,10 @@ static void rb_setup_ids_meta_page(struct ring_buffer_per_cpu *cpu_buffer,
68526852
/* install subbuf ID to kern VA translation */
68536853
cpu_buffer->subbuf_ids = subbuf_ids;
68546854

6855-
meta->meta_page_size = PAGE_SIZE;
68566855
meta->meta_struct_len = sizeof(*meta);
68576856
meta->nr_subbufs = nr_subbufs;
68586857
meta->subbuf_size = cpu_buffer->buffer->subbuf_size + BUF_PAGE_HDR_SIZE;
6858+
meta->meta_page_size = meta->subbuf_size;
68596859

68606860
rb_update_meta_page(cpu_buffer);
68616861
}
@@ -6949,6 +6949,12 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
69496949
!(vma->vm_flags & VM_MAYSHARE))
69506950
return -EPERM;
69516951

6952+
subbuf_order = cpu_buffer->buffer->subbuf_order;
6953+
subbuf_pages = 1 << subbuf_order;
6954+
6955+
if (subbuf_order && pgoff % subbuf_pages)
6956+
return -EINVAL;
6957+
69526958
/*
69536959
* Make sure the mapping cannot become writable later. Also tell the VM
69546960
* to not touch these pages (VM_DONTCOPY | VM_DONTEXPAND).
@@ -6958,11 +6964,8 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
69586964

69596965
lockdep_assert_held(&cpu_buffer->mapping_lock);
69606966

6961-
subbuf_order = cpu_buffer->buffer->subbuf_order;
6962-
subbuf_pages = 1 << subbuf_order;
6963-
69646967
nr_subbufs = cpu_buffer->nr_pages + 1; /* + reader-subbuf */
6965-
nr_pages = ((nr_subbufs) << subbuf_order) - pgoff + 1; /* + meta-page */
6968+
nr_pages = ((nr_subbufs + 1) << subbuf_order) - pgoff; /* + meta-page */
69666969

69676970
nr_vma_pages = vma_pages(vma);
69686971
if (!nr_vma_pages || nr_vma_pages > nr_pages)
@@ -6975,20 +6978,24 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
69756978
return -ENOMEM;
69766979

69776980
if (!pgoff) {
6981+
unsigned long meta_page_padding;
6982+
69786983
pages[p++] = virt_to_page(cpu_buffer->meta_page);
69796984

69806985
/*
6981-
* TODO: Align sub-buffers on their size, once
6982-
* vm_insert_pages() supports the zero-page.
6986+
* Pad with the zero-page to align the meta-page with the
6987+
* sub-buffers.
69836988
*/
6984-
} else {
6985-
/* Skip the meta-page */
6986-
pgoff--;
6989+
meta_page_padding = subbuf_pages - 1;
6990+
while (meta_page_padding-- && p < nr_pages) {
6991+
unsigned long __maybe_unused zero_addr =
6992+
vma->vm_start + (PAGE_SIZE * p);
69876993

6988-
if (pgoff % subbuf_pages) {
6989-
err = -EINVAL;
6990-
goto out;
6994+
pages[p++] = ZERO_PAGE(zero_addr);
69916995
}
6996+
} else {
6997+
/* Skip the meta-page */
6998+
pgoff -= subbuf_pages;
69926999

69937000
s += pgoff / subbuf_pages;
69947001
}

tools/testing/selftests/ring-buffer/map_test.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,20 @@ TEST_F(map, data_mmap)
228228
data = mmap(NULL, data_len, PROT_READ, MAP_SHARED,
229229
desc->cpu_fd, meta_len);
230230
ASSERT_EQ(data, MAP_FAILED);
231+
232+
/* Verify meta-page padding */
233+
if (desc->meta->meta_page_size > getpagesize()) {
234+
void *addr;
235+
236+
data_len = desc->meta->meta_page_size;
237+
data = mmap(NULL, data_len,
238+
PROT_READ, MAP_SHARED, desc->cpu_fd, 0);
239+
ASSERT_NE(data, MAP_FAILED);
240+
241+
addr = (void *)((unsigned long)data + getpagesize());
242+
ASSERT_EQ(*((int *)addr), 0);
243+
munmap(data, data_len);
244+
}
231245
}
232246

233247
FIXTURE(snapshot) {

0 commit comments

Comments
 (0)