Page MenuHomeFreeBSD

Have rtld query the page size from the kernel
ClosedPublic

Authored by andrew on Apr 4 2022, 3:07 PM.
Tags
None
Referenced Files
Unknown Object (File)
Tue, May 14, 8:43 AM
Unknown Object (File)
Apr 4 2024, 10:01 AM
Unknown Object (File)
Mar 4 2024, 8:10 AM
Unknown Object (File)
Jan 31 2024, 7:08 PM
Unknown Object (File)
Jan 14 2024, 8:21 AM
Unknown Object (File)
Dec 11 2023, 2:38 AM
Unknown Object (File)
Oct 22 2023, 8:36 AM
Unknown Object (File)
Oct 7 2023, 9:21 PM
Subscribers

Details

Summary

To allow for a dynamic page size on arm64 have the runtime linker
query the kernel for the currentl page size.

Test Plan

Same rtld binary runs on a kernel built with 4k and 16k pages on arm64

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

andrew requested review of this revision.Apr 4 2022, 3:07 PM

Rtld already has to cope with pagesizes. In particular, look at init_pagesizes() and RTLD_INIT_PAGESIZES_EARLY. The later is actually a remnant of ia64 which might be exactly what you need. This should allow to eliminate all getpagesize() calls from your patch and use pagesizes[0].

It might be best to remove RTLD_INIT_PAGESIZES_EARLY and just do it early unconditionally.

RTLD_INIT_PAGESIZES_EARLY doesn't seem to be needed as the call to init_pagesizes() is before the first call to getpagesize(), even if I use it in place of all users of pagesize[0].

Is there a reason to prefer pageisze[0] over pagesizes()? I have a version of pagesizes() with the sysctl removed as it's never needed that still works.

RTLD_INIT_PAGESIZES_EARLY doesn't seem to be needed as the call to init_pagesizes() is before the first call to getpagesize(), even if I use it in place of all users of pagesize[0].

Is there a reason to prefer pageisze[0] over pagesizes()? I have a version of pagesizes() with the sysctl removed as it's never needed that still works.

sysctl(3) call in the rtld_libc.c version of getpagesize() is for compat case, since in principle almost all auxv entries (except base for relocation) are optional, and allocator does need to know the page size.

Using pagesizes[0] (or better, just pagesize global) avoids function call.

Doesn't in-kernel image activator require some related fixes?

libexec/rtld-elf/map_object.c
136

I must admit this changes ABI.

215

This would cause similar ABI issue, since binary built for 4k page with corresponding alignment would be not runnable.

Initially there will be no compatability for userspace and the kernel built with a different PAGE_SIZE value. I'm working towards userspace having any knowledge of it and would like the arm64 ABI in 14 to not include any hard coded knowledge of the page size. The only place that this will be difficult is jemalloc.

I don't expect a kernel built with 16k PAGE_SIZE will be able to run pre-14 binaries, however this will be a non-default option that the user will need to opt in to with knowledge on what they are doing.

In D34765#788188, @kib wrote:

Doesn't in-kernel image activator require some related fixes?

What fixes would you expect?

libexec/rtld-elf/map_object.c
136

That is expected. Userspace from <= 13 is not expected to run on a kernel built with 16k PAGE_SIZE. It will be a non-default option that the user has to enable with the understanding it will break the ABI.

I would like to make the alignment 64k here on arm64 for 14+. It should be safe as the linker should already use 64k alignment, however I'd expect to keep 4k for older binaries.

  • Use a page size variable directly

I prefer to not use asserts in rtld, at least not in the early parts. They are very hard to debug.

WRT imgact_elf.c of the page size use, it was a question, not the statement.

libexec/rtld-elf/rtld_malloc.c
123 ↗(On Diff #104627)

This file is also used by libthr, and I do not think that page_size is defined there. Look at libthr/thread/thr_malloc.c.

The page size imgact_elf.c uses will be PAGE_SIZE, i.e. 4k or 16k depending on which was used when building the kernel. For AT_PAGESIZES we only initialise the pagesizes kernel array used to populate it with the values the hardware supports, i.e. L3 page size, L2 block size, and if supported the L1 block size.

  • Remove asserts
  • Revert the rtld malloc changes so libthr will build
kib added inline comments.
libexec/rtld-elf/rtld-libc/rtld_libc.c
103

I would add a note there referencing init_pagesizes().

This revision is now accepted and ready to land.Apr 6 2022, 11:20 PM

Add a note to getpagesize

This revision now requires review to proceed.Apr 7 2022, 9:16 AM
This revision is now accepted and ready to land.Apr 7 2022, 1:41 PM
This revision was automatically updated to reflect the committed changes.