macos/arm64上地址空间不使用第一位吗?

问题描述 投票:0回答:1

我使用的是ARM64系统(M1)。

$ uname -m
arm64

这是我用来查找系统上虚拟地址空间范围的 C 程序。

#include <stdlib.h>
#include <stdio.h>
#define _GNU_SOURCE
#include <assert.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>

int main(void) {
    printf("Page size = %d\n", getpagesize());
    
    struct rlimit x;

    getrlimit(RLIMIT_AS, &x);
    printf("Current maximum size = %llx\n", x.rlim_cur);
    printf("Limit on maximum size = %llx\n", x.rlim_max);

    unsigned long long int value = 0;
    value -= 1;
    printf("Maximum float = %llx", value);
    return 0;
}

输出:

Current maximum size = 7fffffffffffffff // 9223372036854775807
Limit on maximum size = 7fffffffffffffff // 9223372036854775807
Maximum float = ffffffffffffffff // 18446744073709551615

最大尺寸似乎是2^63-1。最后一位根本没有被使用。

为什么会这样?在64位系统上,虚拟内存地址范围应该到2^64-1对吧?

我知道地址只使用48位,但这似乎与地址空间的范围无关(为什么32位和64位地址有两种不同的长度?

c memory operating-system arm64
1个回答
0
投票

就arm64硬件而言,EL0和EL1共享一个转换机制,

TTBR0_EL1
TTBR1_EL1
分别控制地址空间的下半部分和上半部分。通常下半部分用于用户态,上半部分用于内核。

但首先要注意的是,

rlimit
与硬件无关。这是关于操作系统的。

XNU 有这个(也被复制到 Apple 的 SDK 中):

#define RLIM_INFINITY   (((__uint64_t)1 << 63) - 1)     /* no limit */

所以这只是“无限制”值。

第二点,尽管有

RLIMIT_AS
的描述,但这与地址空间大小无关。这大约是流程中所有现有映射的总和

arm64 XNU 允许您映射内存的实际最大地址是 0x00007ffffe000000。 该值只是针对 macOS 进行了硬编码。还有一个最小地址,在进程初始化时设置为进程中主二进制文件的基地址(通常为 0x100000000)加上 ASLR 幻灯片。

在 macOS 以外的 Apple 操作系统上,最大地址的规则更复杂,但以下是相关代码位:

osfmk/mach/arm/vm_param.h

#if defined(XNU_PLATFORM_MacOSX) || defined(XNU_PLATFORM_DriverKit)
#define MACH_VM_MAX_ADDRESS_RAW 0x00007FFFFE000000ULL
#else
#define MACH_VM_MAX_ADDRESS_RAW 0x0000000FC0000000ULL
#endif

osfmk/mach/shared_region.h

#define SHARED_REGION_BASE_ARM64                0x180000000ULL
#define SHARED_REGION_SIZE_ARM64                0x100000000ULL

osfmk/arm/pmap/pmap.c

/* end of shared region + 512MB for various purposes */
#define ARM64_MIN_MAX_ADDRESS (SHARED_REGION_BASE_ARM64 + SHARED_REGION_SIZE_ARM64 + 0x20000000)

// Max offset is 13.375GB for devices with "large" memory config
#define ARM64_MAX_OFFSET_DEVICE_LARGE (ARM64_MIN_MAX_ADDRESS + 0x138000000)
// Max offset is 9.375GB for devices with "small" memory config
#define ARM64_MAX_OFFSET_DEVICE_SMALL (ARM64_MIN_MAX_ADDRESS + 0x38000000)

vm_map_offset_t
pmap_max_64bit_offset(
    __unused unsigned int option)
{
    vm_map_offset_t max_offset_ret = 0;

#if defined(__arm64__)
    const vm_map_offset_t min_max_offset = ARM64_MIN_MAX_ADDRESS; // end of shared region + 512MB for various purposes
    if (option == ARM_PMAP_MAX_OFFSET_DEFAULT) {
        max_offset_ret = arm64_pmap_max_offset_default;
    } else if (option == ARM_PMAP_MAX_OFFSET_MIN) {
        max_offset_ret = min_max_offset;
    } else if (option == ARM_PMAP_MAX_OFFSET_MAX) {
        max_offset_ret = MACH_VM_MAX_ADDRESS;
    } else if (option == ARM_PMAP_MAX_OFFSET_DEVICE) {
        if (arm64_pmap_max_offset_default) {
            max_offset_ret = arm64_pmap_max_offset_default;
        } else if (max_mem > 0xC0000000) {
            // devices with > 3GB of memory
            max_offset_ret = ARM64_MAX_OFFSET_DEVICE_LARGE;
        } else if (max_mem > 0x40000000) {
            // devices with > 1GB and <= 3GB of memory
            max_offset_ret = ARM64_MAX_OFFSET_DEVICE_SMALL;
        } else {
            // devices with <= 1 GB of memory
            max_offset_ret = min_max_offset;
        }
    } else if (option == ARM_PMAP_MAX_OFFSET_JUMBO) {
        if (arm64_pmap_max_offset_default) {
            // Allow the boot-arg to override jumbo size
            max_offset_ret = arm64_pmap_max_offset_default;
        } else {
            max_offset_ret = MACH_VM_MAX_ADDRESS;     // Max offset is 64GB for pmaps with special "jumbo" blessing
        }
    } else {
        panic("pmap_max_64bit_offset illegal option 0x%x", option);
    }

    assert(max_offset_ret <= MACH_VM_MAX_ADDRESS);
    assert(max_offset_ret >= min_max_offset);
#else
    panic("Can't run pmap_max_64bit_offset on non-64bit architectures");
#endif

    return max_offset_ret;
}

因此,在 iOS 和其他非 macOS 配置上,如果您有“巨型”地图(可以通过

com.apple.developer.kernel.extended-virtual-addressing
权利获得),则地址大小限制为 0x0000000fc0000000,或者在具有 com.apple.developer.kernel.increased-memory-limit
some
设备上
),否则为 0x00000002a0000000、0x00000002b8000000 或 0x00000003b8000000,具体取决于设备拥有多少物理内存。

请注意,后三个大小可能会发生变化,因为它们是根据共享缓存区域边界的大小计算得出的,而共享缓存区域边界本身也会发生变化。今天的“9.375GB”和“13.375GB”评论也是错误的,因为它们源于

SHARED_REGION_SIZE_ARM64
0xa0000000
的时代。

© www.soinside.com 2019 - 2024. All rights reserved.