32
32
#endif
33
33
34
34
#define CLS_HOST_SYSCTL_BUFFER_SIZE (128 )
35
+ #define CLS_MAX_ARM64_NATIVE_PAGE_SIZE (1024 * 16 )
35
36
36
37
#if CLS_CPU_ARM64
37
- #define CLS_MAX_NATIVE_PAGE_SIZE ( 1024 * 16 )
38
+ #define CLS_MAX_NATIVE_PAGE_SIZE CLS_MAX_ARM64_NATIVE_PAGE_SIZE
38
39
#else
39
40
// return 4K, which is correct for all platforms except arm64, currently
40
41
#define CLS_MAX_NATIVE_PAGE_SIZE (1024 * 4 )
@@ -68,22 +69,32 @@ vm_size_t FIRCLSHostGetPageSize(void) {
68
69
// these types. Turns out that sysctl will not init the data to zero, but it appears
69
70
// that sysctlbyname does. This API is nicer, but that's important to keep in mind.
70
71
72
+ int maxNativePageSize = CLS_MAX_NATIVE_PAGE_SIZE;
73
+
74
+ // On Apple Silicon, we need to use the arm64 page size
75
+ // even if we're in x86 land.
76
+ if (FIRCLSHostIsRosettaTranslated ()) {
77
+ FIRCLSSDKLog (" Running under Rosetta 2 emulation. Using the arm64 page size.\n " );
78
+
79
+ maxNativePageSize = CLS_MAX_ARM64_NATIVE_PAGE_SIZE;
80
+ }
81
+
71
82
pageSize = 0 ;
72
83
size = sizeof (pageSize);
73
84
if (sysctlbyname (" hw.pagesize" , &pageSize, &size, NULL , 0 ) != 0 ) {
74
85
FIRCLSSDKLog (" sysctlbyname failed while trying to get hw.pagesize\n " );
75
86
76
- return CLS_MAX_NATIVE_PAGE_SIZE ;
87
+ return maxNativePageSize ;
77
88
}
78
89
79
90
// if the returned size is not the expected value, abort
80
91
if (size != sizeof (pageSize)) {
81
- return CLS_MAX_NATIVE_PAGE_SIZE ;
92
+ return maxNativePageSize ;
82
93
}
83
94
84
95
// put in some guards to make sure our size is reasonable
85
- if (pageSize > CLS_MAX_NATIVE_PAGE_SIZE ) {
86
- return CLS_MAX_NATIVE_PAGE_SIZE ;
96
+ if (pageSize > maxNativePageSize ) {
97
+ return maxNativePageSize ;
87
98
}
88
99
89
100
if (pageSize < CLS_MIN_NATIVE_PAGE_SIZE) {
@@ -93,6 +104,29 @@ vm_size_t FIRCLSHostGetPageSize(void) {
93
104
return pageSize;
94
105
}
95
106
107
+ // This comes from the Apple documentation here:
108
+ // https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment
109
+ bool FIRCLSHostIsRosettaTranslated () {
110
+ #if TARGET_OS_MAC
111
+ int result = 0 ;
112
+ size_t size = sizeof (result);
113
+ if (sysctlbyname (" sysctl.proc_translated" , &result, &size, NULL , 0 ) == -1 ) {
114
+ // If we get an error, or 0, we're going to treat this as x86_64 macOS native
115
+ if (errno == ENOENT) {
116
+ return false ;
117
+ }
118
+ // This is the error case
119
+ FIRCLSSDKLog (" sysctlbyname failed while trying to get sysctl.proc_translated for Rosetta 2 "
120
+ " translation\n " );
121
+ return false ;
122
+ }
123
+ return result == 1 ;
124
+
125
+ #else
126
+ return false ;
127
+ #endif
128
+ }
129
+
96
130
static void FIRCLSHostWriteSysctlEntry (
97
131
FIRCLSFile* file, const char * key, const char * sysctlKey, void * buffer, size_t bufferSize) {
98
132
if (sysctlbyname (sysctlKey, buffer, &bufferSize, NULL , 0 ) != 0 ) {
0 commit comments