The kernel can be found at Apple Open Source. We show here how to build this XNU version for Raspberry Pi 3(BCM2837).
TBC.
There are some files to modify to get the build successful.
Change the arm64e
(compiling target for M1) in makedefs/MakeInc.def
to arm64
:
ifneq ($(findstring _Sim,$(RC_ProjectName)),)
ARCH_FLAGS_ARM64 = -arch arm64e
else ifneq ($(findstring _host,$(RC_ProjectName)),)
ARCH_FLAGS_ARM64 = -arch arm64e
...
export ARCH_STRING_FOR_CURRENT_MACHINE_CONFIG := arm64e
...
LDFLAGS_KERNEL_ONLY_SUBARCH_arm64e = \
-Wl,-add_split_seg_info \
-Wl,-kernel
to
ifneq ($(findstring _Sim,$(RC_ProjectName)),)
ARCH_FLAGS_ARM64 = -arch arm64
else ifneq ($(findstring _host,$(RC_ProjectName)),)
ARCH_FLAGS_ARM64 = -arch arm64
...
export ARCH_STRING_FOR_CURRENT_MACHINE_CONFIG := arm64
...
LDFLAGS_KERNEL_ONLY_SUBARCH_arm64 = \
-Wl,-add_split_seg_info \
-Wl,-kernel
This disables Pointer Authentication(PAC) extension, because Raspberry Pi has an ARMv8 kernel without such extension in ARMv8.3(M1).
Comment out the WERROR
flag in makedefs/MakeInc.def
like this:
ifeq ($(USE_WERROR),1)
# WERROR := -Werror
endif
Find any refereces of vm_pageout_wait
in the source code (you can also try to compile the kernel and let the compiler find them for you).
Foe example, there is one in iokit/Kernel/IOPMrootDomain.cpp
:
#if defined(XNU_TARGET_OS_OSX)
vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
#endif /* defined(XNU_TARGET_OS_OSX) */
Add !CONFIG_EMBEDDED
into the condition:
#if defined(XNU_TARGET_OS_OSX) && !CONFIG_EMBEDDED
vm_pageout_wait(AbsoluteTime_to_scalar(&deadline));
#endif /* defined(XNU_TARGET_OS_OSX) */
This will suppress the line when compiling for Raspberry Pi, which is an embedded device.
Raspberry Pi is declared as an embedded service in the makefile, which explicitly disables some features. But apparently, Apple does not handle them well.
We need to add !CONFIG_EMBEDDED
in osfmk/vm/vm_map.c
to comment out all the vmmap_high_start
field. The field is not defined under an embedded enviroment.
For instance, we should change:
#if XNU_TARGET_OS_OSX
result->vmmap_high_start = 0;
#endif
to
#if XNU_TARGET_OS_OSX && !CONFIG_EMBEDDED
result->vmmap_high_start = 0;
#endif
We need to remove any PAC extension code. To do so, comment out the #include <arm64/pac_asm.h>
in the files that compiler conplains.
For instance, in osfmk/arm64/exception_asm.h
:
// #include <arm64/pac_asm.h>
#include <pexpert/arm64/board_config.h>
#include "assym.s"
Remove ml_enable_monitor
in osfmk/arm64/arm_vm_init.c
, replace pmap_cs_allow_invalid(vm_map_pmap(map))
in osfmk/arm64/vm_map.c
with 0.
Both of them disable the unintentional calling to PAC-related functions.
In pexpert/arm/pe_serial.c
, change the base address to the one that belongs to Raspberry Pi 3:
vm_offset_t pi3_gpio_base_vaddr = 0x3F200000;
vm_offset_t pi3_aux_base_vaddr = 0x3F215000;
Comment out the base address detection from Apple Device Tree:
#ifdef PI3_UART
/*
if (SecureDTFindEntry("name", "gpio", &entryP) == kSuccess) {
SecureDTGetProperty(entryP, "reg", (void const **)®_prop, &prop_size);
pi3_gpio_base_vaddr = ml_io_map(soc_base + *reg_prop, *(reg_prop + 1));
}
if (SecureDTFindEntry("name", "aux", &entryP) == kSuccess) {
SecureDTGetProperty(entryP, "reg", (void const **)®_prop, &prop_size);
pi3_aux_base_vaddr = ml_io_map(soc_base + *reg_prop, *(reg_prop + 1));
}
*/
if ((pi3_gpio_base_vaddr != 0) && (pi3_aux_base_vaddr != 0)) {
register_serial_functions(&pi3_uart_serial_functions);
}
#endif /* PI3_UART */
Only run this on a Mac:
make SDKROOT=macosx ARCH_CONFIGS=ARM64 MACHINE_CONFIGS=BCM2837 KERNEL_CONFIGS=DEVELOPMENT
You can also replace the DEVELOPMENT
config to RELEASE
.
Finally, there will be a kernel file kernel.<CONFIGS>.bcm2837
in BUILD/obj/<CONFIGS>_ARM64_BCM2837
directory.
Please create an issue if you have any other problems when building XNU.