Skip to content

Generalize the VA39 heap-allocation fallback to any user address-space size - #1107

Open
takano32 wants to merge 2 commits into
pharo-project:pharo-12from
takano32:generalized-va-fallback
Open

takano32 wants to merge 2 commits into
pharo-project:pharo-12from
takano32:generalized-va-fallback

Conversation

@takano32

Copy link
Copy Markdown
Contributor

What

A follow-up to #1079. That PR added a heap-allocation fallback so the VM can start on aarch64 kernels built with CONFIG_ARM64_VA_BITS_39, whose user address space (< 2^39) cannot reach the configured oldSpace base (2^40). It worked, but hard-coded the 39-bit numbers in src/unix/memoryUnix.c:

#define VA39_ADDRESS_LIMIT   ((usqInt)0x8000000000ULL)   /* 2^39 */
#define VA39_FALLBACK_BASE   ((usqInt)0x4000000000ULL)   /* 2^38 */
#define VA39_FALLBACK_LIMIT  ((usqInt)0x7F00000000ULL)   /* 2^39 - 4GB */

This PR replaces those constants with values derived from the user address-space limit measured at run time, so the same code path serves any address-space size (VA36, VA40, VA42, …), not only VA39.

How

findUserAddressSpaceLimit() probes one-page mappings at descending powers of two. With MAP_FIXED_NOREPLACE, both an exact placement and an EEXIST return prove the address is reachable (EEXIST = valid but occupied); anything else means we are past the limit. Where the flag is unavailable (pre-4.17 Linux / non-Linux, where it is #defined to 0) the probe degrades to plain hinting — safe, the window just sits one step lower.

The fallback window is then [limit >> 1, limit - (limit >> 7)). On a VA39 kernel that evaluates to exactly the former constants (base 0x4000000000, limit 0x7F00000000), so behaviour on VA39 hardware is unchanged; a smaller or larger user address space gets a correctly-sized window from the same code.

Why it is low-risk

  • No behaviour change where it already worked. The fallback only triggers when the configured base exceeds the measured limit, so it stays dormant on every VA48 platform — i.e. all of upstream CI — exactly as before. On VA39 it computes the identical window Minimal ARM64 VA39 support, enabling the VM to run on ARM Chromebooks #1079 used.
  • Generated C is byte-identical. The Smalltalk side already recomputes the space-discrimination masks from the address actually obtained (added in Minimal ARM64 VA39 support, enabling the VM to run on ARM Chromebooks #1079), so it needed no change. No source that generates C was touched.
  • Test-only Smalltalk change. VMMemoryMapTest gains testOldSpaceFallbackIsClassifiedCorrectlyForAnyAddressSpaceSize, which checks the masks still classify every space correctly for fallback bases spanning 36- to 47-bit address spaces (the existing VA39 test generalized).

Verified on real hardware

Built natively on an aarch64 VA39 machine (ARM Chromebook class) and booted a stock Pharo 13 image. The probe detects the 2^39 limit and the fallback places oldSpace exactly where #1079 did:

sqAllocateMemory: Requested memory size: 71335936 at: 0x10000000000, ... obtained at: 0x4000000000

eval '3+4' prints 7; no sqAllocateMemory error. This is the same observable outcome as #1079 on this machine — the point being that the generalization does not regress the VA39 case it replaces.

Relation to other work

I could not run the VMMaker simulator suite locally (the bootstrap is unstable on this host for unrelated reasons), so the new test leans on CI to execute; happy to iterate if it surfaces anything. No rush on review.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Dszsb5ALkx1ytH8atZPvEV

PR pharo-project#1079 added a heap-allocation fallback for aarch64 VA39 kernels
whose user address space cannot reach the configured oldSpace base
(2^40), but hard-coded the 39-bit numbers: VA39_ADDRESS_LIMIT (2^39),
VA39_FALLBACK_BASE (2^38) and VA39_FALLBACK_LIMIT (2^39 - 4GB).

Replace those constants with values derived from the user
address-space limit measured at run time. findUserAddressSpaceLimit()
probes one-page mappings at descending powers of two; with
MAP_FIXED_NOREPLACE both an exact placement and EEXIST prove an address
is reachable. The fallback window is then [limit>>1, limit - limit>>7),
which on a VA39 kernel evaluates to exactly the former constants
(base 0x4000000000, limit 0x7F00000000) - so behavior on VA39 hardware
is unchanged - while any smaller-or-larger user address space (VA36,
VA40, VA42, ...) gets a correctly-sized window from the same code path.

The Smalltalk side already recomputes the space-discrimination masks
from the address actually obtained, so it needed no change; the mask
recomputation is only newly exercised at other bases. VMMemoryMapTest
gains testOldSpaceFallbackIsClassifiedCorrectlyForAnyAddressSpaceSize,
which checks the masks still classify all spaces for fallback bases
spanning 36- to 47-bit address spaces.

The fallback only triggers when the configured base exceeds the
measured limit, so it stays dormant on every VA48 platform (all
upstream CI) exactly as before. No Smalltalk sources that generate C
changed, so the generated C is byte-identical.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dszsb5ALkx1ytH8atZPvEV
CI on PR pharo-project#1107 failed with "SmallInteger does not understand
#isClassifiedCorrectly" in
testOldSpaceFallbackIsClassifiedCorrectlyForAnyAddressSpaceSize. The helper
was written as `assertOldSpaceFallbackToBase: aBase isClassifiedCorrectly`,
which is not a valid keyword pattern, and the call site
`self assertOldSpaceFallbackToBase: fallbackBase isClassifiedCorrectly`
parses `isClassifiedCorrectly` as a unary send to the integer.

Rename the helper to assertOldSpaceFallbackIsClassifiedCorrectlyAtBase: and
fix the call site. Test intent and assertions are unchanged. The other
VMMemoryMapTest cases, including the VA39-specific fallback test, passed in
the same CI run.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TauFFpUVFxALPoA5UZKr7E
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant