Runtime: [ARM64/Unix] Support for 16K & 64K page sizes

Created on 11 Feb 2017  路  17Comments  路  Source: dotnet/runtime

ARM64 support 4K, 16K, & 64K page sizes.

Current tip is only supporting 4K

arch-arm64 area-VM-coreclr os-linux

All 17 comments

@sdmaclea it looks like this is necessary for arm64. I have installed arch Linux for ARM64 on my Raspberry Pi3 and the kernel in that distro has page size set to 64kB.
Without explicit support for the 64kB page size, coreclr crashes left and right.
Now the ugly thing is that I guess the page size is a distro specific thing, which complicates our future plans for having distro agnostic coreclr package, unless we make coreclr detect page size at runtime and use it at all the places.
Since I needed to run some tests on ARM64 and the Arch Linux is the only free distro that officially supports aarch64 on Raspberry Pi3, I have tried to patch coreclr to support 64kB pages statically. I have succeeded, at least for the basic hello world like testing apps I am using. So I would like to summarize the places I needed to modify as a reference for a future real work on enabling new page sizes:

  • CORINFO_PAGE_SIZE definition in src/inc/corinfo.h b/src/inc/corinfo.h
  • PAGE_SIZE definition in src/inc/switches.h
  • VIRTUAL_PAGE_SIZE constant in src/pal/src/include/pal/virtual.h
  • Added alignment of allocation size to the page size in ClrVirtualAllocAligned

Then there is GC that can work independent of the real page size on its own page size or it can also be modified to use the same page size (I've tried both ways).
For the first way, when GC still uses 4096 bytes page size, we need to define OS_PAGE_SIZE to 4096 before the first include in src/gc/gcsvr.cpp and src/gc/gcwks.cpp
For the second way, when the GC would use the real page size, I needed to modify:

  • OS_PAGE_SIZE definition in src/gc/env/gcenv.base.h to 65536
  • add x15, x12, x14, lsr dotnet/coreclr#11 to add x15, x12, x14, lsr dotnet/coreclr#15 in JIT_WriteBarrier in src/vm/arm64/asmhelpers.S
  • card_byte_shift definition in src/vm/gchelpers.cpp from 11 to 15

CC: @jkotas, @Maoni0
@Maoni0, I am not sure if the GC should use the real page size or stay on the 4096 bytes page. The reason why I am asking is that if we wanted the GC to use the real page size and we would want to detect the page size at runtime instead of having separate coreclr package for each page size, then we would have to figure out how to handle it without a negative perf impact.

the GC should use the real page size or stay on the 4096 bytes page

The OS_PAGE_SIZE constant is used in the GC for several different purposes: actual OS page size, convenient 4kB constant, etc. We should decouple these. I believe that the alignment to actual OS page won't be used in any perf-critical situations and thus we can just use the dynamic value for it.

Let's say that somebody builds special kernel that has large pages only, and thus the OS page size will be 2MB+. The GC should perform well on it.

card_byte_shift definition in src/vm/gchelpers.cpp

card_size is one of the places where the OS_PAGE_SIZE is used as convenient 4kB constant. We should change it to be hardcoded to 4k/8k instead.

This looks similar to the issue that Go (golang) has had to address. I'll point you at https://github.com/golang/go/issues/10180 for the issues that surfaced there, as a point of comparison.

@vielmetti thank you for the pointer!

@janvorli there aren't many places GC would need to use the real page size, most of which come from when we use the write watch on Windows, we do need to use the real page size so revisit_written_page* (when used on Windows, when used on Linux we can choose whatever size we want as long as it's not too big. so we chose the OS page size to be consistent with Windows. if we used large pages like 2mb+ obviously we would not want to use that).

@janvorli I have periodically been hitting this issue. I am interested in fixing this if you want to assign this to me. I think your notes are sufficient for me to make substantial progress. I would suggest the GC clean-up and refactoring be done in a separate/follow-on issue. Initial goal one arm64 binary that runs on 4K& 64K pages (and untested 16K page support)

@sdmaclea that would be great. I am working on other issues for the 2.0.0 release now, so it would be a welcome help.

CORINFO_PAGE_SIZE was removed as part of dotnet/coreclr#10273

Plan looks like this

  • reproduce @janvorli work with GC still using 4096 bytes page with hard coded page_size.
  • verify hello world runs with page size hard coded
  • Run full default regression on 64K PS arm64 platform see if hard coded solution is functionally complete. Fix issues....
  • GC Stress might be a good idea here too?
  • Replace hard coded with dynamic page size determination. Should I introduce FEATURE_DYNAMIC_PAGESIZE or just use TARGET_ARM64?
  • Run full regression non 64K & 4K arm64 platforms. Possibly GC Stress too.

Number of places use page size as a convenient 4k constant. They should not be switched to dynamic page size. Determining what should be switched and what should stay at 4k is probably the hardest part of this work.

Replace hard coded with dynamic page size determination. Should I introduce FEATURE_DYNAMIC_PAGESIZE or just use TARGET_ARM64?

Ideally, the dynamic OS page size would be used by default, without ifdefs. Yes, it will be an extra instruction here and there, but that's fine. I do not think there should be any perf critical computations that involve the OS page size.

All tests are failing when using native images from crossgen (generated on a 64k page machine) Looks like either crossgen and/or the native image loader needs to be updated as well.

I was able to get crossgen to work

I ran full regression on dotnet/coreclr#10891 . There are 76 tests failing with segmentation fault out of 10600+. Investigating

I looked at one failure, it was happening in the GC as it was trying to increase the heap allocation. Since this is happening with the GC hacked to think think the OS page size is 4K, I am going to ignore the current errors and switch to using the actual OS page size (since I think this is the intended design). I will keep the card table at 4K.

I pushed an additional patch to dotnet/coreclr#10891 to use 64K pages with GC. With that version, test run looked pretty clean.

dotnet/coreclr#10891 was closed in favor of

dotnet/coreclr#10959 Fixes the issues with loading native images
dotnet/coreclr#10981 Fixes the basic runtime issues @janvorli described in the email

There are two other related issues
dotnet/coreclr#10982 For running debugger on 64K pages
dotnet/coreclr#11017 To revisit GC changes to reduce code which depends on OS page size.

Currently requires dotnet/coreclr#10981 & dotnet/coreclr#11413

Merged

Was this page helpful?
0 / 5 - 0 ratings

Related issues

noahfalk picture noahfalk  路  3Comments

omariom picture omariom  路  3Comments

sahithreddyk picture sahithreddyk  路  3Comments

chunseoklee picture chunseoklee  路  3Comments

yahorsi picture yahorsi  路  3Comments