-
Notifications
You must be signed in to change notification settings - Fork 1.1k
RISC-V: detect virtual address space at runtime using hwprobe #1296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -41,6 +41,13 @@ terms of the MIT license. A copy of the license can be found in the file | |
| #else | ||
| #include <sys/mman.h> | ||
| #endif | ||
| #if defined(__riscv) || defined(_M_RISCV) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We cannot use extensions like (mmm, but maybe riscV is so recent that we can assume that all C compilers on riscV support
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have seen it used in an other place so I assumed it was fine, but I realized now that it was guarded by |
||
| #if __has_include(<sys/hwprobe.h>) | ||
| #include <sys/hwprobe.h> | ||
| #elif __has_include(<asm/hwprobe.h>) | ||
| #include <asm/hwprobe.h> | ||
| #endif | ||
| #endif | ||
| #elif defined(__APPLE__) | ||
| #include <AvailabilityMacros.h> | ||
| #include <TargetConditionals.h> | ||
|
|
@@ -187,6 +194,52 @@ static void unix_detect_physical_memory( size_t page_size, size_t* physical_memo | |
| #endif | ||
| } | ||
|
|
||
| // Detect the virtual address bits (currently Linux/RISC-V only) | ||
| static size_t unix_detect_virtual_address_bits(void) | ||
| { | ||
| #if defined(__riscv) || defined(_M_RISCV) | ||
| #ifdef RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS | ||
| struct riscv_hwprobe probe = { | ||
| .key = RISCV_HWPROBE_KEY_HIGHEST_VIRT_ADDRESS, | ||
|
aurel32 marked this conversation as resolved.
|
||
| }; | ||
|
|
||
| // Prefer the GNU libc interface if available, as it can also use the VDSO | ||
| #if __has_include(<sys/hwprobe.h>) | ||
| if (__riscv_hwprobe(&probe, 1, 0, NULL, 0) == 0) { | ||
| #else | ||
| if (syscall(__NR_riscv_hwprobe, &probe, 1, 0, NULL, 0) == 0) { | ||
| #endif | ||
| // If a key is unknown to the kernel, its key field will be cleared to -1. | ||
| if (probe.key != -1) { | ||
| return MI_SIZE_BITS - mi_clz((uintptr_t)probe.value); | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| // Fallback to checking /proc/cpuinfo for older kernels | ||
| int fd = mi_prim_open("/proc/cpuinfo", O_RDONLY); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, i'll fix that |
||
| if (fd >= 0) { | ||
| char buf[4096]; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is a large buffer on the stack; maybe 1024 bytes is enough to find if
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That works fine for now on a recent CPU, but that might be tight if more extensions are added. Here is for instance the first 1024 bytes on a SpacemiT K3: Would that be acceptable to go down to 2048 bytes instead? |
||
| ssize_t nread = mi_prim_read(fd, &buf, sizeof(buf)); | ||
| mi_prim_close(fd); | ||
| if (nread >= 1) { | ||
| if (_mi_strnstr(buf, nread, "sv39")) { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should also test if
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, i'll fix that |
||
| return 39; | ||
| } | ||
| if (_mi_strnstr(buf, nread, "sv48")) { | ||
| return 48; | ||
| } | ||
| if (_mi_strnstr(buf, nread, "sv57")) { | ||
| return 57; | ||
| } | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| // default: MI_MAX_VABITS | ||
| return MI_MAX_VABITS; | ||
| } | ||
|
|
||
| void _mi_prim_mem_init( mi_os_mem_config_t* config ) | ||
| { | ||
| long psize = sysconf(_SC_PAGESIZE); | ||
|
|
@@ -199,6 +252,7 @@ void _mi_prim_mem_init( mi_os_mem_config_t* config ) | |
| config->has_overcommit = unix_detect_overcommit(); | ||
| config->has_partial_free = true; // mmap can free in parts | ||
| config->has_virtual_reserve = true; // todo: check if this true for NetBSD? (for anonymous mmap with PROT_NONE) | ||
| config->virtual_address_bits = unix_detect_virtual_address_bits(); | ||
|
|
||
| // disable transparent huge pages for this process? | ||
| #if (defined(__linux__) || defined(__ANDROID__)) && defined(PR_GET_THP_DISABLE) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.